Sending Null Object Pointers to DLL

BlitzMax Forums/BlitzMax Programming/Sending Null Object Pointers to DLL

Gabriel(Posted 2009) [#1]
I'm trying to call a DLL which uses a lot of optional object parameters. Needless to say, if you don't want to use them, you pass NULL in C++ and they get ignored. Simple enough, right? Except:

Method CallFunction:Int(Obj1:SomeObject = Null, Obj2:SomeObject = Null)
   If Obj1<>Null
      RunTimeError "This never happens"
   End If
   If Obj2<>Null
      RunTimeError "This never happens either"
   End If
   BMX_CallFunction(Obj1,Obj2) ' THESE POINTERS ARE NEVER RECOGNISED AS NULL IN C++
   BMX_CallFunction(Null,Null) ' THESE ARE
End Method


So what appears to be happening is that Obj1 and Obj2 are null objects but for some reason if you try to pass them as a pointer (I figured I might as well make use of BlitzMax implicitly converting back and forth between Byte Ptr and Object since Mark has ignored all my prior requests to make it explicit) it somehow sends an invalid but not NULL byte pointer instead? If I have to have a whole bunch of conditional statements in every function call to spot Null objects, I'm going to have a very slow interface to a DLL. There must be a better way.

If I change :SomeObject to :Byte Ptr in the function prototype, it works fine.

Here's a simple example without any external calls to show how messed up this is:


Type Thingy
   Field Stuff:Int
End Type

Global A:Thingy=Null

DoSomething(A)

Function DoSomething(B:Thingy)
	If B=Null
		Local C:Byte Ptr=B
		Print Int(C)
	End If
End Function



N(Posted 2009) [#2]
Here's a very short explanation of Null objects..

They aren't Null. More specifically, they don't point to Null. They point to bbNullObject. Big difference. The only way you can pass true null is if you're using a pointer and not passing an object proper, or if your C++ code tests for bbNullObject.


SebHoll(Posted 2009) [#3]
If you are calling BlitzMax function from external code, you should always force them to the C standard calling conventions, by putting "C" after the function declaration line... E.g.

Function DoSomething(B:Thingy) "C"
    'Blah
EndFunction
I'm not necessarily saying that this is what's wrong here, just that it helps solve a few headaches long term when things start working in Debug, but not Release mode (or viceversa).

Edit: Yep, sorry. Ignore me... :P


Gabriel(Posted 2009) [#4]
So really, the best you can do if you have a function (as I currently do) which takes six optional objects is :

Function DoSomething(SomethingElse:Int, O1:Object=Null, O2:Object=Null, O3:Object=Null, O4:Object=Null, O5:Object=Null, O6:Object=Null)
Local B1:Byte Ptr=Null, etc..
If O1<>Null
   B1=O1
End If
etc..
BMX_DoSomething(SomethingElse, B1, B2, B3, B4, B5, B6)
End Function


I mean quite aside from the overhead I'm adding to every function, it gives me a mass of code for a single function call.

EDIT: Seb, I have no idea what you're talking about. I'm talking about calling a C++ DLL from BlitzMax. Nothing is calling BlitzMax.


N(Posted 2009) [#5]
Or pass bbNullObject instead of Null when calling the function in C/C++.


Gabriel(Posted 2009) [#6]
Of course the easiest way to do this would be to avoid default parameters altogether and overload functions instead. Except, of course, that we can't overload functions either.

Well I can't see a viable solution other than having multiple versions of the functions, each leaving out a different combination of default parameters. It means myriads more functions but at least it doesn't mean you need 6 conditions for one function call, which is ludicrous.