Building DLL for ZGE

Use of external libraries (DLLs) from ZGE.

Moderator: Moderators

Post Reply
User avatar
diki
Posts: 140
Joined: Thu Sep 11, 2008 7:53 pm
Location: GMT+1
Contact:

Building DLL for ZGE

Post 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?
Last edited by diki on Tue Feb 16, 2010 7:44 pm, edited 4 times in total.
User avatar
VilleK
Site Admin
Posts: 2274
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Post 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.
User avatar
diki
Posts: 140
Joined: Thu Sep 11, 2008 7:53 pm
Location: GMT+1
Contact:

Post 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:

Code: Select all

int InOut( int i )
{
    return i;
}
and a .zge-project which invokes that function; it reliably crashes on my machine every time. do you get the same results?
Attachments
dlltest.zip
(3.77 KiB) Downloaded 871 times
User avatar
VilleK
Site Admin
Posts: 2274
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Post 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.
User avatar
diki
Posts: 140
Joined: Thu Sep 11, 2008 7:53 pm
Location: GMT+1
Contact:

Post 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.
User avatar
VilleK
Site Admin
Posts: 2274
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Post 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
User avatar
diki
Posts: 140
Joined: Thu Sep 11, 2008 7:53 pm
Location: GMT+1
Contact:

Post 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).
User avatar
jph_wacheski
Posts: 1005
Joined: Sat Feb 16, 2008 8:10 pm
Location: Canada
Contact:

Post 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 :)
iterationGAMES.com
User avatar
diki
Posts: 140
Joined: Thu Sep 11, 2008 7:53 pm
Location: GMT+1
Contact:

Post 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?
Attachments
dlltest v24.zip
contains .zgeproj, .dll and sources
(360.9 KiB) Downloaded 895 times
User avatar
VilleK
Site Admin
Posts: 2274
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Post 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!
User avatar
jph_wacheski
Posts: 1005
Joined: Sat Feb 16, 2008 8:10 pm
Location: Canada
Contact:

Post 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!
Attachments
dlltest v25.zgeproj
testing,. .
(5.37 KiB) Downloaded 896 times
iterationGAMES.com
User avatar
y offs et
Posts: 418
Joined: Wed Apr 22, 2009 4:26 pm
Location: BC, Canada

Post 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. :shock:
I figure it to be a rounding error(is it 4 decimal places ZGE rounds at?).
"great expectations"
User avatar
diki
Posts: 140
Joined: Thu Sep 11, 2008 7:53 pm
Location: GMT+1
Contact:

Post 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 ;)
Post Reply