静态库和共享对象、符号是否共享? 我正在创建一个帮助器来在C++类和Lua对象之间创建多重继承。因为Lua将C/C++用户对象存储为void*,所以在检索对象时很难执行安全强制转换 // main.cpp #include <iostream> #include <memory> #include <string> #include <lua.hpp> #include "Common.h" using namespace std; class LuaDeleter { public: void operator()(lua_State *L) { lua_close(L); } }; typedef unique_ptr<lua_State, LuaDeleter> LuaState; int main(void) { LuaState L(luaL_newstate()); luaL_requiref(L.get(), "_G", luaopen_base, 1); luaL_requiref(L.get(), "package", luaopen_package, 1); // This will dlopen() and dlclose() string code = "local battery = require \"battery\""; LuaeClass::createConverter<int, int>("Int", "Int"); if (luaL_dostring(L.get(), code.c_str()) != LUA_OK) { cerr << lua_tostring(L.get(), -1) << endl; } return 0; }

静态库和共享对象、符号是否共享? 我正在创建一个帮助器来在C++类和Lua对象之间创建多重继承。因为Lua将C/C++用户对象存储为void*,所以在检索对象时很难执行安全强制转换 // main.cpp #include <iostream> #include <memory> #include <string> #include <lua.hpp> #include "Common.h" using namespace std; class LuaDeleter { public: void operator()(lua_State *L) { lua_close(L); } }; typedef unique_ptr<lua_State, LuaDeleter> LuaState; int main(void) { LuaState L(luaL_newstate()); luaL_requiref(L.get(), "_G", luaopen_base, 1); luaL_requiref(L.get(), "package", luaopen_package, 1); // This will dlopen() and dlclose() string code = "local battery = require \"battery\""; LuaeClass::createConverter<int, int>("Int", "Int"); if (luaL_dostring(L.get(), code.c_str()) != LUA_OK) { cerr << lua_tostring(L.get(), -1) << endl; } return 0; },c++,lua,C++,Lua,比如说, 如果你有 class A { } class B { } class C : public A, public B { } 并且将C类型的对象传递给Lua,通过C实例的地址,当需要将其转换为B时,C++编译器将自动将指针与C中的B位置对齐,因此,将空指针从C直接转换为B是不安全的。 为了避免这个问题,我使用了一种转换器。在Lua中,对象以字符串形式包含其名称,因此当您需要将对象从类型转换为其他类型时,它会使用如下转换器: 转换器[“B”][“C”](mypointer,myresul

比如说,

如果你有

class A { }
class B { }
class C : public A, public B { }

并且将C类型的对象传递给Lua,通过C实例的地址,当需要将其转换为B时,C++编译器将自动将指针与C中的B位置对齐,因此,将空指针从C直接转换为B是不安全的。 为了避免这个问题,我使用了一种转换器。在Lua中,对象以字符串形式包含其名称,因此当您需要将对象从类型转换为其他类型时,它会使用如下转换器:

转换器[“B”][“C”](mypointer,myresultpointer)

这是帮助创建这些转换器的类:

// Common.h

#include <functional>
#include <memory>
#include <unordered_map>
#include <string>

typedef std::function<void (void *, void *)> LuaConverter;

typedef std::unordered_map<
        std::string,
        std::unordered_map<
            std::string,
            LuaConverter
        >
    > LuaConverters;

class LuaeClass {
public:
    static LuaConverters converters;

public:
    template <class From, class To>
    static void createConverter(const std::string &fromName,
                    const std::string &toName)
    {
        converters[toName][fromName] = [&] (void *ptr, void *result) -> void {
            std::shared_ptr<From> *from = static_cast<std::shared_ptr<From> *>(ptr);
            *((std::shared_ptr<To> *)result) = std::static_pointer_cast<To>(*from);
        };
    }
};
//Common.h
#包括
#包括
#包括
#包括
typedef std::函数LUA转换器;
typedef std::无序_映射<
std::字符串,
std::无序图<
std::字符串,
LUA转换器
>
>LUA转化者;
类LuaeClass{
公众:
静态变换器;
公众:
模板
静态void createConverter(const std::string和fromName,
const std::string和toName)
{
转换器[toName][fromName]=[&](无效*ptr,无效*结果)->void{
std::shared_ptr*from=静态_cast(ptr);
*((std::shared_ptr*)result)=std::static_pointer_cast(*from);
};
}
};
此类被编译为静态库,在项目中多次使用

对象需要作为共享_ptr传递(它还解决了所有权和删除问题)。但是,当用作静态库时,它工作良好

然后,我有一个简单的模块电池,作为共享对象编译,并链接到公共库

对于本示例的范围,它不包含太多函数,但实际上使用了LuaeClass:

// Battery.cpp

#include <lua.hpp>

#include "Common.h"

class Battery {
public:
    int getPercent() {
        return 100;
    }
};

extern "C" int luaopen_battery(lua_State *L)
{
    LuaeClass::createConverter<Battery, Battery>("Battery", "Battery");

    return 0;
}
//Battery.cpp
#包括
#包括“Common.h”
等级电池{
公众:
int getPercent(){
返回100;
}
};
外部“C”内部luaopen_电池(lua_状态*L)
{
LuaeClass::createConverter(“电池”、“电池”);
返回0;
}
它被编译为名为battery.so的共享对象,Lua将使用dlopen()和dlcose()加载它

最后,主要问题。它还链接到common,并使用它创建对象

// main.cpp

#include <iostream>
#include <memory>
#include <string>

#include <lua.hpp>

#include "Common.h"

using namespace std;

class LuaDeleter {
public:
    void operator()(lua_State *L) {
        lua_close(L);
    }
};

typedef unique_ptr<lua_State, LuaDeleter> LuaState;

int main(void)
{
    LuaState L(luaL_newstate());

    luaL_requiref(L.get(), "_G", luaopen_base, 1);
    luaL_requiref(L.get(), "package", luaopen_package, 1);

    // This will dlopen() and dlclose()
    string code = "local battery = require \"battery\"";

    LuaeClass::createConverter<int, int>("Int", "Int");

    if (luaL_dostring(L.get(), code.c_str()) != LUA_OK) {
        cerr << lua_tostring(L.get(), -1) << endl;
    }

    return 0;
}
//main.cpp
#包括
#包括
#包括
#包括
#包括“Common.h”
使用名称空间std;
Luadelleter类{
公众:
void运算符()(lua_State*L){
卢厄关闭(L);
}
};
typedef unique_ptr LuaState;
内部主(空)
{
LuaState L(luaL_newstate());
luaL_requiref(L.get(),“_G”,luaopen_base,1);
luaL_requiref(L.get(),“package”,luaopen_package,1);
//这将导致dlopen()和dlclose()
string code=“本地电池=需要电池”;
LuaeClass::createConverter(“Int”、“Int”);
if(LUA_dostring(L.get(),code.c_str())!=LUA_OK){

cerr静态库的代码和全局/静态数据将注入链接它的每个模块。因此,对于您的情况,您的项目中存在多个
LuaeClass::converters
实例。您需要在链接静态库的每个模块中调用
luaopen_battery()

我不确定您的崩溃是否与静态链接有关,但我很确定您使用了一个复杂的实现

您要解决的第一个问题是将
void*
安全地转换为
A*,B*,C*
。您要将哪个类/接口导出到Lua?如果它是
类C
,您可以在类C中定义以下方法:

void pushThis(lua_State *L);
static C* getThis(lua_State *L, int idx);
这两种方法都使用
C*
,因此您不需要转换函数。您可以。如果需要
B*
,只需:

B* b = (B*)C::getThis(L, idx);

,您可能不需要SyddypTr.SydDypTR不利于删除GC对象收集Lua对象时的C++对象(因为SydDypTR仍然存在堆中),相反,必须将.LBP>构建为共享库,LI/PUP很可能同时拥有库和主库的独立副本。(以及全局
LuaeClass::converter
变量的独立副本)。我刚刚尝试过,它也崩溃了。您是否违反了“静态LuaConverters converters”的要求?请参阅示例,从发布的代码中,似乎没有“converter”是的,这是唯一一行定义在Common中的。cpp:LuaConverter LuaeClass::converters;我忘了添加它,然后,如果底层对象不是C而是C的子对象(又名D或E),会发生什么呢?另外,对于u gc,它已经完成了,并且只调用共享的_ptr析构函数:)@如果底层对象是C的子对象,它会从C继承
pushThis
方法,不是吗?而且
C::getThis
仍然有效。我考虑过这一点,这是可能的,但这将要求所有对象都继承这个基类。我会挖掘它。谢谢:)。然而,luabind通过累加做了类似的事情/向下转换(因此它不需要继承特定的基类)