theman
theman

Reputation: 345

calling a C++ DLL from LuaJIT

I know I can't use FFI to load in a C++ DLL (only C will work), so how do I go about doing this? If I need to use a wrapper, how exactly do I get started with that?

EDIT: I cannot change the DLL in any way whatsoever.

Upvotes: 2

Views: 1035

Answers (2)

Colonel Thirty Two
Colonel Thirty Two

Reputation: 26549

You can try mangling the names manually in the FFI cdefs, but different compilers use different name mangling schemes, not to mention that referring to the functions would be awkward.

Rather than manually mangling the names in the cdef, I recommend writing some wrapper in C. While tedious, it's not too difficult. The gist of it is that the C side of it treats classes as opaque structs to pass around to the wrapper functions. See this site for more details and some gotchas, though.

Here's a sample snippet of a wrapper that I use for Box2D:

#include <Box2D/Box2D.h>

#ifdef __linux__
    #define CEXPORT extern "C"
#else
    #define CEXPORT extern "C" __declspec(dllexport)
#endif


// ///////////////////////////////////////////////////////
// World

CEXPORT b2World* b2World_new(b2Vec2* gravity) {
    return new b2World(*gravity);
}
CEXPORT void b2World_destroy(b2World* world) {
    delete world;
}
CEXPORT b2Body* b2World_createBody(b2World* world, const b2BodyDef* def) {
    return world->CreateBody(def);
}
CEXPORT void b2World_destroyBody(b2World* world, b2Body* body) {
    world->DestroyBody(body);
}
CEXPORT void b2World_step(b2World* world, float32 timeStep, int32 velIters, int32 posIters) {
    world->Step(timeStep, velIters, posIters);
}
CEXPORT b2Body* b2World_getBodyList(b2World* world) {
    return world->GetBodyList();
}

And the corresponding cdecl:

typedef struct b2World b2World;

b2World* b2World_new(b2Vec2*);
void     b2World_destroy(b2World*);
b2Body*  b2World_createBody(b2World*, const b2BodyDef*);
void     b2World_destroyBody(b2World*, b2Body* body);
void     b2World_step(b2World*, float, int32_t, int32_t);
b2Body*  b2World_getBodyList(b2World*);

Upvotes: 1

Bruno Ferreira
Bruno Ferreira

Reputation: 1651

You can use a C++ DLL. You need to export the functions like this (in MSVC):

extern "C" __declspec(dllexport)

Due to C++ name mangling (used for overloading), your function signature will not be the same as C naming. For example, this function:

int foo(char* a, int b, double c)

Might be exported as something like foo@12abunchoflettershere using C++ naming, instead of foo, as C naming would be.

Please note that extern "C" does not mean that your code is pure C. You may use C++ normally. This is still valid:

extern "C" __declspec(dllexport) void foo(char *a, int b, std::shared_ptr<Foo> ptr)

Upvotes: 2

Related Questions