Compiling a .dll from bmx code?
BlitzMax Forums/BlitzMax Programming/Compiling a .dll from bmx code?
| ||
Exactly as the title describes. |
| ||
You can't BM has inofficially the support for generating DLLs but you will need to do some stuff by hand (manually calling bmk from command line and manually create the DEF file upfront with the exported function declaration) |
| ||
Thats contradicting Dreamora..... |
| ||
You can here's an example: 1. create any folder where you'll create your dll in. the file names I'll tell you refer to this folder. 2. create a file "DLLTest.bmx" 3. this should be the file content: Strict Framework brl.blitz Function Product ( A , B ) Return A * B EndFunction4. create a file "DLLTest.def" 5. here's the file's content: EXPORTS Product=bb_Product6. open a command prompt 7. if you haven't added the "bin" directory of your BlitzMax installation to the "Path" environment variable, you need to change the current directory to this directory using the CD command. 8. call bmk.exe makelib bmx-file-pathfor debug or bmk.exe makelib -r bmx-file-pathfor release version ("bmx-file-path" needs to be a path to the "DLLTest.bmx" file) 9. the dll is now created, it's named "DLLTest.dll" - to test whether the dll is working do the following: 10. create a file "DLLCaller.bmx" 11. the file's contents are: Strict Framework brl.blitz Import pub.win32 Local Library = LoadLibraryA ( "DLLTest.dll" ) If Not Library WriteStdout "Library not found!~n" Return EndIf Local Product ( A , B ) = GetProcAddress ( Library , "Product" ) If Not Product WriteStdout "Product function not found!~n" Return EndIf WriteStdout "The product of 3 and 5 is " + Product ( 3 , 5 ) + ".~n" FreeLibrary Library Extern "Win32" Function FreeLibrary ( Library ) EndExtern12. build and run the file, if the output is The product of 3 and 5 is 15.you've successfully built and tested a dll using BlitzMax |
| ||
I got an error on the command prompt part. T:\Program Files\BlitzMax\bin>bmk.exe makelib -r ..\test1\DLLTest.bmx Compiling:DLLTest.bmx flat assembler version 1.66 3 passes, 329 bytes. Linking:DLLTest.dll T:/Program Files/BlitzMax/bin/ld.exe: cannot find T:/Program Files/BlitzMax/lib/dllcrt2.o Build Error: Failed to link T:/Program Files/BlitzMax/test1/DLLTest.dll Press any key to continue . . . What is dllcrt2.o? EDIT: I looked in my lib folder and found a file named "crt2.o", is it possible this just needs to be renamed or do I need to rebuild my modules? |
| ||
move dllcrt2.o from your MinGW\lib directory into your BlitzMax\lib directory. |
| ||
T:\Program Files\BlitzMax\bin>bmk.exe makelib DLLTest.bmx Linking:DLLTest.dll T:/Program Files/BlitzMax/bin/ld.exe: cannot open T:/Program: No such file or directory Build Error: Failed to link T:/Program Files/BlitzMax/bin/DLLTest.dll Press any key to continue . . . ..don't tell me I have to reinstall bmax to a location with no spaces :( |
| ||
i tried it myself, and it seems just the project itself must be on a path with no spaces. |
| ||
Okay, that worked.. |
| ||
So how would I return data to the parent program from the dll without ending the execution of the function (without using the command "Return")?? |
| ||
The only part of BlitzMax I have had problems with in a dll is MaxGUI. It would be nice if this worked, because sometimes you have an options interface for import/export plugins. |
| ||
Just use another function for that, or a var parameter, or a pointer. |
| ||
So like... in the dll "Global Var$ = "hello" and in the caller "var = GetProcAddress ( Library , "var" )" then in the def "var=bb_var"?? |
| ||
You can only export Functions from a dll, so more like this: 'DLL Function GetData( output:Int Var) output = 10 EndFunction 'APP Global data:Int GetData( data) or this: 'DLL Function InitDll:Int() Return your_data EndFunction Function DoSomethingElse() EndFunction 'APP Global data:Int = InitDll() DoSomeThingElse() |
| ||
I'm having trouble trying to get that to work.. DLLTest2.bmx Strict Framework brl.blitz Function GetData( output:Int Var) output = 10 EndFunction DllCaller2.bmx Strict Framework brl.blitz Import pub.win32 Global data:Int = 0 Local Library = LoadLibraryA ( "DLLTest2.dll" ) If Not Library WriteStdout "Library not found!~n" Return EndIf Local GetData ( A ) = GetProcAddress ( Library , "GetData" ) If Not Getdata WriteStdout "GetData function not found!~n" Return EndIf GetData( data ) WriteStdout data FreeLibrary Library Extern "Win32" Function FreeLibrary ( Library ) EndExtern DLLTest2.def EXPORTS GetData=bb_GetData I get "Unhandled Memory Exception Error" when trying to call "GetData( data )". |
| ||
You need to declare the function pointer with var as well.Local GetData ( A:Int Var ) = GetProcAddress ( Library , "GetData" ) That should do it =) |
| ||
Okay, it worked, thanks. And one more question, when I call a function from a dll, does it pause the execution of the parent program? EDIT: Ofcourse it does! |
| ||
The dll code you call is executed in the same thread.. so, it's just like calling one of your own program's functions (ie, when the dll function returns, your code continues at the next instruction) |
| ||
Figured that, thanks. |
| ||
You can only export Functions from a dll Not quite, globals can also be exported, it's just important that the caller now needs to refer to the symbol as pointer.Here's an example: DLLTest.bmx: Strict Framework brl.blitz Global VariableDLLTest.def: EXPORTS Variable=bb_VariableDLLCaller.bmx: Strict Framework brl.blitz Import pub.win32 Local Library = LoadLibraryA ( "DLLTest.dll" ) If Not Library WriteStdout "Library not found!~n" Return EndIf Local Variable Ptr = Int Ptr GetProcAddress ( Library , "Variable" ) If Not Variable WriteStdout "Variable not found!~n" Return EndIf Variable [ 0 ] = 53 WriteStdout "Variable is " + Variable [ 0 ] + ".~n" FreeLibrary Library Extern "Win32" Function FreeLibrary ( Library ) EndExternThe calling instance always needs to use the [0] when accessing the variable. If I remember correctly, it was in version 1.12 or 1.14 where you could write: Local Variable Var = Var Int Ptr GetProcAddress ( Library , "Variable" )and then you could access the variable as normal, so "Variable = value" to write and "Variable" to read values, without any need for [0] - but this feature disapeared since version 1.18 I think. The only thing that can't be exported from dlls are types and objects, the problem is that the type would either exist twice, once in the dll and once in the main programm, or the caller couldn't access the object's fields and methods because it has no declaration of the types. P.S.: I'm sorry, I've forgotten to tell you about copying the dllcrt2.o file, but Khomy Prime explained it perfectly. |
| ||
Yeah, thanks for that example though, it did just what I needed. |
| ||
I think you need to add "win32" to the end of every function in both the dll and main program source. I also think you need to have GCEnter() as the first line of every dll function. |