2

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

编辑:我无法以任何方式更改 DLL。

4

2 回答 2

2

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

extern "C" __declspec(dllexport)

由于 C++ 名称修改(用于重载),您的函数签名将与 C 命名不同。例如,这个函数:

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

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

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

extern "C" __declspec(dllexport) void foo(char *a, int b, std::shared_ptr<Foo> ptr)
于 2014-05-29T16:06:27.037 回答
1

您可以尝试在 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-30T01:55:18.437 回答