我知道我无法使用FFI加载C ++ DLL(只有C可以工作),所以我该怎样做呢?如果我需要使用包装器,我究竟该如何开始使用它?
编辑: 我无法以任何方式更改DLL。
答案 0 :(得分:2)
您可以使用C ++ DLL。您需要导出这样的函数(在MSVC中):
extern "C" __declspec(dllexport)
由于C ++名称修改(用于重载),您的函数签名将与C命名不同。例如,这个函数:
int foo(char* a, int b, double c)
可以使用C ++命名导出类似foo@12abunchoflettershere
的内容,而不是foo
,就像C命名一样。
请注意,extern "C"
并不意味着您的代码是纯粹的C.您可以正常使用C ++。这仍然有效:
extern "C" __declspec(dllexport) void foo(char *a, int b, std::shared_ptr<Foo> ptr)
答案 1 :(得分:1)
您可以尝试在FFI cdefs中手动修改名称,但不同的编译器使用不同的名称修改方案,更不用说引用这些函数会很尴尬。
我不建议在cdef中手动修改名称,而是建议在C中编写一些包装器。虽然单调乏味,但并不太难。它的要点是它的C端将类视为不透明的结构,以传递给包装函数。 See this site了解更多细节和一些陷阱。
这是我用于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*);