Я знаю, что не могу использовать FFI для загрузки DLL C++ (подойдет только C), так как мне это сделать? Если мне нужно использовать обертку, как именно мне начать с этим?
РЕДАКТИРОВАТЬ: я никак не могу изменить DLL.
Я знаю, что не могу использовать FFI для загрузки DLL C++ (подойдет только C), так как мне это сделать? Если мне нужно использовать обертку, как именно мне начать с этим?
РЕДАКТИРОВАТЬ: я никак не могу изменить DLL.
Вы можете попробовать изменить имена вручную в cdefs FFI, но разные компиляторы используют разные схемы изменения имен, не говоря уже о том, что обращение к функциям было бы неудобным.
Вместо того, чтобы вручную изменять имена в 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*);
Вы можете использовать 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)
extern "C"
в том, что Компилятор C++ не искажает имя. Если вы используете extern "C"
, вам не нужно беспокоиться об искажении имени.
- person Colonel Thirty Two; 30.05.2014
extern "C"
, а затем сразу же сказать, что сигнатура функции не будет такой же, как именование C, что неверно для функций C.
- person Colonel Thirty Two; 30.05.2014
extern "C"
является изменение имени.
- person Bruno Ferreira; 30.05.2014