Ive had a search and there seems to be a few differences of opinion. Is it possible (and stable) to create a dll/s in blitzmax and if so... are there any small guides/samples?
DLL creation
BlitzMax Forums/BlitzMax Programming/DLL creation hmm interesting question. Could we create a .DLL that could be used in other programs? In other languages?
Theres countless examples in the forums, and as far as i know its pretty stable.
And since they are normal DLLs any application can use them.
But for completeness il put it all here in one place.
First heres some helper tools to help automate the process.
makedef.bmx - creates def files from blitzmax sources (see the 'EXPORT appended to functions in the dll source)
makelib.cmd - for easy creation of def file & compiling dll (allows spaces in the path as well as drag & drop!
You also need to copy dllcrt2.o from your mingw\lib dir to your blitzmax\lib dir. (thanks jsp!)
And add blitzmax\bin to your PATH environment variable.
And heres the actual application + dll sources
app.bmx
dlltest.bmx
Compiling the dll & application:
EDIT: makedef.bmx didnt handle Rem/EndRem properly & added Include handling.
EDIT2: fixed batch file to handle drag & drop
And since they are normal DLLs any application can use them.
But for completeness il put it all here in one place.
First heres some helper tools to help automate the process.
makedef.bmx - creates def files from blitzmax sources (see the 'EXPORT appended to functions in the dll source)
Framework BRL.Blitz Import BRL.StandardIO Import BRL.Stream Import BRL.FileSystem SuperStrict If AppArgs.Length <= 1 Then Local fn:String = StripExt(StripDir(AppArgs[0])) Print fn + ": makes exports def file from blitzmax source" Print "syntax:" Print "~t" + fn + " filename.bmx" Print "~t- creates filename.def of functions marked with 'EXPORT" End EndIf ' create output def file Local defn:String = StripExt(AppArgs[1]) + ".def" Global def:TStream = WriteStream( defn) If Not def Then WriteStderr "** error writing to def file: " + defn + "~n" exit_(1) EndIf def.WriteLine( "EXPORTS") ' keep track of rem/endrem Global remblock:Int ' read the input source If Not ParseSource( AppArgs[1]) Then WriteStderr "~n** there were errors parsing the source files~n" def.Close() exit_(1) EndIf def.Close() End Function ParseSource:Int( fn:String) Local stream:TStream = ReadStream( fn) If Not stream Then WriteStderr "** error reading input file: " + fn + "~n" Return False EndIf ' read each line from input While Not stream.Eof() Local i:Int, s:String = stream.ReadLine().Trim() If StartsWith( s, "Rem") Then If (s.Length > 3) Then If ((s[3] = Asc("'")) Or (s[3] = Asc(" ")) Or (s[3] = Asc("~t"))) Then remblock :+ 1 EndIf Else remblock :+ 1 EndIf ElseIf StartsWith( s, "EndRem") Then If (s.Length > 6) Then If ((s[6] = Asc("'")) Or (s[6] = Asc(" ")) Or (s[6] = Asc("~t"))) Then remblock :- 1 EndIf Else remblock :- 1 EndIf ElseIf (StartsWith( s, "Function ") Or StartsWith( s, "Function~t")) And EndsWith( s, "'EXPORT") Then If remblock = 0 Then s = s[9..] i = s.Find("(") If i <> -1 Then s = s[..i] i = s.Find( ":") If i <> -1 Then s = s[..i] def.WriteLine( "~t" + s + "=bb_" + s) EndIf EndIf ElseIf StartsWith( s, "Include ") Then If remblock = 0 Then s = s[9..s.Length-1] If Not ParseSource( s) Then stream.Close() Return False EndIf EndIf EndIf Wend stream.Close() Return True EndFunction ' case insensitive versions Function StartsWith:Int( s:String, val:String) Return s[..val.Length].ToLower() = val.ToLower() EndFunction Function EndsWith:Int( s:String, val:String) Return s[s.Length - val.Length..].ToLower() = val.ToLower() EndFunction
makelib.cmd - for easy creation of def file & compiling dll (allows spaces in the path as well as drag & drop!
@echo off if not %1 == "" ( cd %~dp1 makedef %~nx1 pushd . command /c bmk makelib -r %~n1 popd )
You also need to copy dllcrt2.o from your mingw\lib dir to your blitzmax\lib dir. (thanks jsp!)
And add blitzmax\bin to your PATH environment variable.
And heres the actual application + dll sources
app.bmx
Framework BRL.Blitz Import BRL.StandardIO Import PUB.win32 SuperStrict ' load the dll Local lib:Int = LoadLibraryA( "dlltest.dll") If Not lib Then RuntimeError "Library not found!" ' get its function Global ShowMessage() "Win32" = GetProcAddress( lib, "ShowMessage") If Not ShowMessage Then RuntimeError "ShowMessage() not found!" ' test the dll function ShowMessage() ' free the dll FreeLibrary( lib) Extern "Win32" Function FreeLibrary:Int( lib:Int) EndExtern
dlltest.bmx
Framework BRL.Blitz SuperStrict Const COMPILE_DLL:Int = True Function ShowMessage() "Win32" 'EXPORT If COMPILE_DLL Then GCEnter() MessageBoxA 0, "Hello world from DLL!", "MessageBox", 0 EndFunction Extern "Win32" Function MessageBoxA:Int( hwnd:Int, message$z, title$z, buttons:Int) EndExtern
Compiling the dll & application:
makelib dlltest.bmx bmk makeapp -r app.bmx
EDIT: makedef.bmx didnt handle Rem/EndRem properly & added Include handling.
EDIT2: fixed batch file to handle drag & drop
Don't forget to copy dllcrt2.o from your MinGW\lib directory into your BlitzMax\lib directory.
And to have drag and drop working from any location you may like to add a cd command (blitzmax bin directory) to the makelib.cmd file.
And to have drag and drop working from any location you may like to add a cd command (blitzmax bin directory) to the makelib.cmd file.
Oops, forgot about that one.. =)
Its also good idea to add your blitzmax bin dir to your path, as you should with mingw.
Its also good idea to add your blitzmax bin dir to your path, as you should with mingw.
whoah.... I may have to play with this when I have time, but it sounds like I could make my little 2d engine be useable from any other language. hmm.... BIG hmm....
whoah.... I may have to play with this when I have time, but it sounds like I could make my little 2d engine be useable from any other language. hmm.... BIG hmm....
You're going to have a lot of issues with garbage collection if you try.