DLL creation

BlitzMax Forums/BlitzMax Programming/DLL creation

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

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)
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