BlitzMax types and dlls

BlitzMax Forums/BlitzMax Programming/BlitzMax types and dlls

JoshK(Posted 2008) [#1]
I have found that it passing BlitzMax types to and from a BlitzMax dll works perfectly, even with other languages. I would recommend declaring the variables as a byte ptr in the main program, and having the BlitzMax dll return the type.

DLL function:
Function SubmeshSurface_:TSurface(hsubmesh:Int) "win32"
	GCEnter()
	Local submesh:TSubmesh
	submesh=TSubmesh(HandleToObject(hsubmesh))
	Return submesh.surface
EndFunction

Function CountVertices_:Int(surface:TSurface) "win32"
	GCEnter()
	Return surface.CountVertices()
EndFunction

Main program:
Global SubmeshSurface:Byte Ptr(hsubmesh:Int) "win32"
Global CountVertices:Int(surface:Byte Ptr) "win32"

Obviously it is your responsibility to manage the memory, but for types that always get stored in a list and have a Free() command, this approach will work just fine.

The only problem I have found is that the BlitzMax dll does not seem to recognize Null when it is passed. When I pass Null to this DLL function from the main program, the dll always thinks that a valid object was passed:
Function LoadMesh_:Int(cs:Byte Ptr,oparent:TEntity) "win32"
	GCEnter()
	Local parent:TEntity
	Local mesh:TMesh
	Local path$
	If oparent=Null Notify "null parent" Else Notify "Something was passed, muthafucka!"
	parent=TEntity(oparent)
	'parent=TEntity(HandleToObject(hparent))
	path=String.fromcstring(cs)
	mesh=LoadMesh(path,parent)
	If mesh Return mesh.handle
EndFunction



JoshK(Posted 2008) [#2]
Interestingly, when I got a "null" value from a dll function like this:
Function TestObject:Object() "win32"
	GCEnter()
	Return Null
EndFunction


And passed it back to the dll, it was recognized as Null!


JoshK(Posted 2008) [#3]
When the main program passes Null to the dll, and that object is converted into a byte pointer, the value is 8. This makes sense, because of the BMX object offset, which I assume is 8 bytes.

I could do this to check if a byte ptr passed to the dll is a null object:
If Int(ObjectPointer(parameter:Object))=8 parameter=Null
...but I am a little scared of reading memory not allocated by the program.

What is really needed here is a way to convert a BlitzMax object to a pointer and back. BlitzMax does not allows a Byte Ptr to Object conversion. I would like to request this be changed.

Type TFoo
	
EndType


Local p:Byte Ptr
Local foo:TFoo


foo=New TFoo

p=ObjectToPointer(foo)

foo=TFoo(PointerToObject(p))


Function ObjectToPointer:Byte Ptr(o:Object)
	Return o
EndFunction

Function PointerToObject:Object(b:Byte Ptr)
	Return b
EndFunction



JoshK(Posted 2008) [#4]
Here's an example with binaries and source:
http://www.leadwerks.com/post/objectpointers.zip

dll.bmx:
Type TFoo
	Global list:TList=New TList
	
	Field name$="I am a foo."
	
	Method New()
		list.addfirst(Self)
	EndMethod
	
EndType

Function GetNullObject:Object() "win32"
	GCEnter()
	Return Null
EndFunction

Function GetObject:Object() "win32"
	GCEnter()
	Local foo:TFoo=New TFoo
	Return foo
EndFunction

Function SetObject(foo:TFoo) "win32"
	GCEnter()
	If foo
		Notify foo.name
	Else
		Notify "Foo does not exist."
	EndIf
EndFunction


main.bmx:
hlib=LoadLibraryA("dll.dll")

Global GetObject:Byte Ptr() "win32"
Global SetObject(foo:Byte Ptr) "win32" 
Global GetNullObject:Byte Ptr() "win32"

GetObject=getprocaddress(hlib,"GetObject")
GetNullObject=getprocaddress(hlib,"GetNullObject")
SetObject=getprocaddress(hlib,"SetObject")

Local foo:Byte Ptr

foo=GetObject()

'This works fine:
SetObject foo

'This works, too:
SetObject GetNullObject()

'This crashes:
SetObject Null

End


Here is one workaround to make the dll not crash:
Function SetObject(foo:TFoo) "win32"
	GCEnter()
	If Int(ObjectPointer(foo))=8 foo=Null
	If foo
		Notify foo.name
	Else
		Notify "Foo does not exist."
	EndIf
	
	Function ObjectPointer:Byte Ptr(o:Object)
		Return o
	EndFunction
	
EndFunction

But this feels like a hack and I am very wary of it. I am afraid BlitzMax might be creating empty objects or something other than just handling a data pointer.