【问题标题】:calling a C++ DLL from LuaJIT从 LuaJIT 调用 C++ DLL
【发布时间】:2014-07-19 05:06:07
【问题描述】:

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

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

【问题讨论】:

    标签: c++ c dll lua luajit


    【解决方案1】:

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

    extern "C" __declspec(dllexport)
    

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

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

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

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

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

    【讨论】:

    • 好的,有道理。有没有办法我仍然可以在不修改 DLL 的情况下调用 C++ 函数?也许调用一个用 C 编写的可以处理名称修改的不同 DLL?
    • -1:extern "C" 的整点是the C++ compiler doesn't mangle the name。如果您使用extern "C",则不必担心名称错误。
    • @ColonelThirtyTwo 这正是我所说的。
    • @user2030964 你可以正常使用C++。请记住,类中的函数不能是虚拟的或重载的。可能还有一些限制,但我现在不记得了。
    • @BrunoFerreira 不,你没有。您说要使用extern "C",然后立即说“函数签名将与C 命名不同”,这对于C 函数是不正确的。
    【解决方案2】:

    您可以尝试在 FFI cdefs 中手动修改名称,但不同的编译器使用不同的名称修改方案,更不用说引用函数会很尴尬。

    我建议不要手动修改 cdef 中的名称,而是建议用 C 编写一些包装器。虽然繁琐,但并不难。它的要点是它的 C 端将类视为不透明的结构,以传递给包装函数。不过,See this site 了解更多详情和一些问题。

    这是我用于 Box2D 的包装器的示例 sn-p:

    #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*);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-26
      • 2020-02-07
      • 2012-03-04
      • 2019-11-30
      • 2019-04-18
      相关资源
      最近更新 更多