从LuaJIT调用C++ DLL

我知道我不能使用 FFI 加载 C++ DLL(只有 C 可以工作),那么我该如何做到这一点?如果我需要使用包装器,我该如何开始?

编辑:我不能以任何方式更改 DLL。

点赞
用户3537339
用户3537339

你可以使用一个C++ DLL。你需要这样导出函数(在MSVC中):

extern "C" __declspec(dllexport)

由于C++的名称重载机制(名称修饰),你的函数签名将不同于C的命名。例如,这个函数:

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

可能会被导出为像foo@12abunchoflettershere这样的东西,使用C++命名,而不是像C的命名那样被导出为foo

请注意,extern "C"并不意味着你的代码是纯C。你仍然可以正常地使用C++。这是有效的:

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

2014-05-29 16:06:27
用户646619
用户646619

你可以尝试在 FFI cdefs 中手动混淆名称,但是不同的编译器使用不同的名称混淆方案,更不用说引用这些函数会很麻烦。

与其在 cdef 中手动混淆名称,我建议编写一些 C 的包装器。虽然有点繁琐,但并不太难。它的关键在于 C 端将类视为不透明的结构体,传递给包装器函数。查看此网站以获取更多详细信息和注意事项。

以下是我用于 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();
}

以及相应的 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*);
2014-05-30 01:55:18