Page 1 of 1
Building DLL for ZGE
Posted: Sun Feb 14, 2010 7:05 pm
by diki
To help people looking for the info, here's a paste:
(the following applies to a CodeBlocks + MinGW setup)
- 1) ZGE requires "stdcall" as calling convention. It's also common to specify C-linkage. Declare functions like:
Code: Select all
void DLL_EXPORT STDCALL FunctionName( int argument )
// or
void DLL_EXPORT __stdcall FunctionName( int argument )
// or
extern "C" void DLL_EXPORT STDCALL FunctionName( int argument )
2) To avoid name-mangling in GCC, the following Linker setting is also required:
Main menu: Project -> Build options -> GNU GCC Compiler -> Linker settings -> Other linker options: -Wl,--kill-at
----
original post follows ----
hi,
while trying to adapt Box2D for ZGE i found that Box2D uses pointers to refer to its physics objects instances. i thought it would make sense to couple the box2d bodies with zge models and for that purpose store the pointers inside the model. trying to force-fit the memory address into an int failed, however; that might either be my buggy code or the general incongruency between pointer & int (although i thought a pointer could be represented by an int). optimistically assuming that my code was clean and the pointer really can not be represented by an int, what would you suggest as an alternative solution? a sort of coupling mechanism inside the dll, like a list/vector that stores the pointers alongside an arbitrary integer?
Posted: Sun Feb 14, 2010 8:01 pm
by VilleK
Pointers and integers are both 32-bit values so it should work provided something like this:
Your wrapper function that creates a box2d-instance and returns this instance-pointer cast as a int-handle.
int diki_create_box()
//In your c-code you do something like "return new Box2dObject();"
ZGE reads this value as an int and keeps a copy of it for further calls.
void diki_update(int handle)
float diki_getAngle(int handle)
float diki_getPositionX(int handle)
float diki_getPositionY(int handle)
Finally:
void diki_destroy_box(int handle)
//In your c-code you do something like "delete (*Box2dObject)handle;"
If it is not working then post some of your C-wrapper code and we can look at it together.
Note that your C-code need not make any casts, they can use pointers as normal, it is enough to make the ZExternalLibrary define the parameters as integers.
Posted: Mon Feb 15, 2010 7:38 pm
by diki
hmmm,
after trying several different ways of passing pointers around, i only ever got Assertion Failures or flat out crashes :(
but i'm optimistic that the flat out crashes are only a bug in the ZGE implementation :) i attached a simple DLL with a function like the following:
and a .zge-project which invokes that function; it reliably crashes on my machine every time. do you get the same results?
Posted: Mon Feb 15, 2010 8:00 pm
by VilleK
Another hurdle I forgot to mention is the trickery of getting the right calling convention of your functions.
I believe your function is implicitly declared as calling convention "cdecl" but the one ZGE requires is "stdcall".
Try
int DLL_EXPORT STDCALL InOut( int i )
or
int DLL_EXPORT __stdcall InOut( int i )
When I google on this it seems to be common to also specify C-linkage in front of the function like this:
extern "C" int DLL_EXPORT STDCALL InOut( int i )
Hope this helps! Let me know if it doesn't and I'll install a C-compiler to dig further.
Posted: Tue Feb 16, 2010 2:45 am
by diki
hi ville,
thanks for the tips! the STDCALL convention turned the crash into a more elegant error: now a window titled "ZZDC Error" containing the function name ("InOut") pops up. adding C-linkage does not change that, i'm afraid.
i'm currently using CodeBlocks and the GNU GCC Compiler / MinGW Package, if that might have something to do with it.
Posted: Tue Feb 16, 2010 2:29 pm
by VilleK
I found out that you need to make this setting:
Main menu: Project -> Build options -> GNU GCC Compiler -> Linker settings -> Other linker options:
-Wl,--kill-at
http://forums.codeblocks.org/index.php?topic=4351.0
This is because stdcall makes gcc generate a different name for the function using name-mangling. "InOut@4" etc. The above setting removes this behavior.
Also I've improved error checking and messages in the beta, so download it again if you want:
http://www.zgameeditor.org/files/ZGameEditor_beta.zip
Posted: Tue Feb 16, 2010 7:22 pm
by diki
that did it; very nice!
still takes some time to get comfortable with c++ again, but i just got the basic simulation working (creating a world, creating a body & storing a pointer to the body in zge, advance the time step, have zge ask & receive position data of that body).
Posted: Tue Feb 16, 2010 8:08 pm
by jph_wacheski
Very cool,. hope you can work it all out, and are willing to share it when its working well, so I can have a go,. . could be fun
Posted: Tue Feb 16, 2010 10:22 pm
by diki
it's coming along nicely ... but another little bug showed up.
the attached .zgeproj works fine for about 3 boxes, then starts to ignore the angle of the boxes. when commenting out the line
Code: Select all
App.Caption = intToStr( b2dll_GetAngle( b2DynamicBody ) * 1000 );
in the Box2D_DynamicBox > OnUpdate > ZExpression, the application window goes black shortly after startup. the corresponding function in the code is
Code: Select all
float DLL_EXPORT STDCALL b2dll_GetAngle( b2Body* body ){
float32 angle = body->GetAngle();
return angle; }
changing float32 to float does not fix it... any ideas?
Posted: Wed Feb 17, 2010 7:37 am
by VilleK
This was a bug in zge not handling float return values correctly. Normal values are returned in eax-register but float-values are returned on the floating point stack. It is fixed now so update your beta version.
Your example now works and looks very cool!
Posted: Wed Feb 17, 2010 3:27 pm
by jph_wacheski
Yup, this is working very well over here! I had a look at the source and it is interesting,.(i can somewhat understand it!) I didn't realise you need to address each function you want to use from the library,. lots of setup to get this working eh,. how much of the functionality of the Box2D library do you intent to cover?
One thing I noticed, just messing with this, is that the method I normaly use to place objects when spawning them i.e. 'Box2D_DynamicBox.position.X=random(0,.3);' when spawning them does not work here,. I suppose due to the box being added to the simulation and then instantly taking its position from the sim.? Anyway, I am quite interested in how this works out,. DLL suport will allow for lots of interesting experiments,. and some cool games for sure!
Posted: Wed Feb 17, 2010 3:48 pm
by y offs et
I noticed on V.24 that when the box slides, there's a variation in the value; anywhere from 4712-4716. And one time, the falling box actually missed to the left of the first tipper, and set up a whole new scenario.
I figure it to be a rounding error(is it 4 decimal places ZGE rounds at?).
Posted: Wed Feb 17, 2010 10:08 pm
by diki
jph_wacheski wrote:how much of the functionality of the Box2D library do you intent to cover?
i'll try to include everything i can understand ... most of it can probably be included by simply 'exposing' it to ZGE with the proper declarations. but i'm still reading up on the docs. there will probably be a point where i either don't see a use for some special function or simply loose interest ;) - but of course i'm going to open the source (no idea how to go about that, though).
jph_wacheski wrote:One thing I noticed, just messing with this, is that the method I normaly use to place objects when spawning them i.e. 'Box2D_DynamicBox.position.X=random(0,.3);' when spawning them does not work here
i don't know why it does not work here - after all, the position variable is set before box2d creates the body... hm. but you could play nice, keep the Model code untouched & just randomize the SpawnModel's position ;)