Sending Null Object Pointers to DLL
BlitzMax Forums/BlitzMax Programming/Sending Null Object Pointers to DLL
| ||
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 |
| ||
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. |
| ||
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 EndFunctionI'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 |
| ||
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. |
| ||
Or pass bbNullObject instead of Null when calling the function in C/C++. |
| ||
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. |