DLL creation, second attempt

BlitzMax Forums/BlitzMax Programming/DLL creation, second attempt

Sweenie(Posted 2005) [#1]
I couldn't resist Halo's DLL-creation challenge so I gave it another go.

This time I think I came up with a pretty good solution.
It doesn't require MingW and therefore it doesn't need to be a module.

You will find the download below...
Check the readme and the demo.bmx file inside the ziparchive for further instructions...
http://www.svenberra.net/MakeDLL.zip

Yes, the commandlinetool looks exactly like the one skn3[ac] made. Hope you don't mind skn3[ac] :)

Hopefully someone could improve the tool and make the process even simpler.


fredborg(Posted 2005) [#2]
This version works with spaces in filepaths/names:
Oh, and top job it seems to work perfectly!


Sweenie(Posted 2005) [#3]
Thanks for the addition!


Tom(Posted 2005) [#4]
Beers are on me!


fredborg(Posted 2005) [#5]
Any ideas why message requesters in the dll's produces a memory access violation, when it's called?


Sweenie(Posted 2005) [#6]
I'm currently investigating that.
I'm not quite sure how Bmax messageboxes works, but maybe it's expecting something to be initialized before using them and when running the blitzapp as a dll, that init-function never runs. Just speculating though.
It's the same for the Print function.

When browsing through the symbols inside some blitzapps I noticed an entry called bb_main, which is probably the entrypoint for the exe's.
The entry point for the dll's is the DllMain function.

I let you know if I find something.


Sweenie(Posted 2005) [#7]
As I suspected the Notify function is a member of an instance called Driver(TSystemDriver)
My best guess is that the Driver-object never get's initialized when the app is run as a dll.

But since Notify is a wrapped method for the User32 MessageBoxA function you could use that API function directly instead.
Like this...


Framework BRL.Blitz

Extern "win32"
 Function MessageBoxA:Int(hWnd:Byte Ptr,lpText$z,lpCaption$z,uType:Int)
End Extern

Function DllMain(hinstDLL:Byte Ptr,fdwReason:Int,lpvReserved:Byte Ptr)"win32"
 Return True
End Function

Function AddIntegers:Int(a:Int,b:Int)"win32"	'EXPORT   
 MessageBoxA(Null,"The result of "+a+" + "+b+" = "+(a+b),"Result:",0)
End Function



[Edit]
And the Common Dialogue api(comdlg32, not linked by default) if you want fileopen/save requesters, printerselector and so on.


skn3(Posted 2005) [#8]
nice one :) gonna throw myn in de recycle bin now ;)


Airilsm(Posted 2006) [#9]
Sweenie,
I try but has this error..

Parsing sourcefile...
Exported functions:
AddIntegers
GetText
Creation of demo.dll failed


Chris C(Posted 2006) [#10]
is there any way to capture the output of the system_ call?


Sweenie(Posted 2006) [#11]
@Mag, Do you have spaces somewhere in the path?, if so, try fredborg's version.

@Chris C.
Not sure, but maybe there is some apifunction that let you set the stdout.
Try searching codeproject.com, they usually have examples and tutorials for such things.


BlitzSupport(Posted 2016) [#12]
Does this still work for anyone? I'm using fredborg's version (post #2 in this thread), but although it successfully builds a DLL, it doesn't seem to work with anything (trying the DLL from BlitzMax and PureBasic, building 32-bit DLL, testing in 32-bit programs).

By default, I get a warning:

Exported functions:
 Test
 Hello
I:\SpiderOak\DevTools\Blitz\BlitzMax\bin\ld.exe: warning: cannot find entry symbol _bb_DllMain; defaulting to 10001000
Creation of testdll.dll successful



The resulting DLL contains my functions (checked with Dependency Walker), but doesn't appear to load at all in BMX/PB, so I'm suspecting it's something to do with the entry point error -- where is _bb_DllMain defined/found?

I tried deleting the "-e _bb_DllMain" from the ld.exe command line it calls, but although that gives no errors, the DLL still doesn't load.

This is my DLL program:


SuperStrict

Function Test ()'EXPORT
	Print "Testing"
End Function

Function Hello:Int ()'EXPORT
	Return 1
End Function


... and quick program that loads/tests the DLL:

Local lib:Byte Ptr = LoadLibraryA ("testdll.dll")

Global Test:Int ()
Global Hello:Int (name:Byte Ptr)

If lib

	Print "Hi"

	Test = GetProcAddress (lib, "Test")
	Hello = GetProcAddress (lib, "Hello")
	
	If Test And Hello Then Print "OK"
	
EndIf


I'm currently testing in bmx-ng (for some reason, makedll.exe crashes here when built from 'vanilla' and run from the command line), but I don't see that this would matter given it's just reading/writing files and calling an external program, ie. ld.exe...

Anyone know how to resolve the "_bb_DllMain" problem? I suppose ld.exe is meant to be generating this?


Kryzon(Posted 2016) [#13]
From the Windows documentation, the entry point seems to be something you can't remove:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682596(v=vs.85).aspx

So I would first test if it works by adding a dummy DllMain function like Sweenie did in post #7:
Function DllMain:Int(hinstDLL:Byte Ptr,fdwReason:Int,lpvReserved:Byte Ptr)"win32"
 Return True
End Function
EDIT: That article says it's optional actually, but I'd test it anyway... maybe the default entry point is not being created.


BlitzSupport(Posted 2016) [#14]
Well spotted, Kryzon, thanks for that, will try when I get home tonight.


BlitzSupport(Posted 2016) [#15]
Awesome, that did it, first try! Many thanks (yet again).

EDIT: Hmm, the DLL worked from BlitzMax, but not from PureBasic. Will investigate. Maybe need to add the other standard DLL functions, look at possible name-mangling, etc...


grable(Posted 2016) [#16]
Did you get it to call the DllMain defined in blitzmax??
Since BRL.AppStub defines its own which blitz uses to initialize various things, i dont see how without it breaking.

EDIT: I modified BRL.AppStub to always call a blitz defined DllMain and it works quite nicely :)
Though its best to keep it as its own module and only use it when DllMain is required. (by using the -b switch for bmk to specify alternate appstub)

NOTE: that i called it BRL.AppStub_DLL, and the blitz defined DllMain must not be marked "win32".

brl.mod\appstub_dll.mod\appstub.win32.c

EDIT-2: Simplified above source.


BlitzSupport(Posted 2016) [#17]

Did you get it to call the DllMain defined in blitzmax??


Hmm, no idea, but it ran! Maybe that's why it didn't work in PureBasic... ?

I'll have a look at your stuff tonight, thanks for posting!


grable(Posted 2016) [#18]
Hmm, no idea, but it ran! Maybe that's why it didn't work in PureBasic... ?

Im guessing so. If all you did was replace the entry point it would skip the initialization of the GC and any imported modules.

The reason it worked in BlitzMax might be because it shared some state...
Though as far as i know they shouldnt, as dlls have their own copy of the runtime and cant even share object instances. Go figure :p


BlitzSupport(Posted 2016) [#19]
I didn't manage to get this working, but weirdly, thanks to Bobysait and Filax, I've just found this:

http://mdt.bigbang.free.fr/blitz3dfr/_fofo/index.php?topic=2703.0

With this, I can build a working 32-bit DLL from vanilla BlitzMax, and it's so easy! The result works in BlitzMax and PureBasic (when set to use its 32-bit compiler).

Now to put together an archive for Brucey, to see if he can get 'bmk makelib' working in bmx-ng (oh, hi, Brucey!). Would be nice to be able to do it from there, plus maybe 64-bit DLLs...


RustyKristi(Posted 2016) [#20]
Hey James,

You can also check my older posts re DLL's working with NG. If I can find that link I'll post it here later.


BlitzSupport(Posted 2016) [#21]
Thanks, Rusty -- I found your thread regarding calling external DLLs from bmx-ng, but I think that's a separate issue, as the problem here seems to relate to "bmk makelib" not producing the function exports in the resulting DLL.

I've opened an 'issue' at https://github.com/bmx-ng/bmk/issues/25 in the hope that Brucey wants a challenge!


RustyKristi(Posted 2016) [#22]
Ah k got it.