我創建了一個幫助器,在C++類和Lua對象之間創建多重繼承。因爲Lua將C/C++用戶對象存儲爲void *,所以在檢索對象時很難做到安全的強制轉換。靜態庫和共享對象是共享符號嗎?
例如,
,如果你有
class A { }
class B { }
class C : public A, public B { }
而且你通過C型到Lua的對象,你傳遞的C實例的地址,當你需要它轉換到B, C++編譯器會自動將指針對準C中B的位置,因此將void *指針從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);
};
}
};
該類被編譯爲靜態庫在項目中多次使用。
對象需要作爲shared_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.so,Lua中會使用的dlopen()和dlcose()加載它。
最後主要是。它也鏈接到通用,並用它來創建對象。
// 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;
}
要總結:
- Common.cpp,COMMON.H被編譯爲簡單的靜態庫(libcommon.a)
- Main.cpp的,編譯和鏈接libcommon.a
- Battery.cpp,編譯爲共享對象並鏈接到libcommon.a
退出時的主要segfaults,核心文件表示它在std :: function <>析構函數>所以我想它是多次調用同一個指針,是嗎?
靜態庫數據是否在所有代碼中共享?我怎樣才能避免這個問題?
的核心
#0 0x0000000000404062 in std::__1::function<void (void*, void*)>::~function()()
#1 0x0000000000404025 in std::__1::function<void (void*, void*)>::~function()()
下一個跟蹤的開始僅僅是不可讀的,無法使用。
也將libcommon構建爲共享庫,可能Battery和Main都擁有自己獨立的庫副本(並因此獨立拷貝全局'LuaeClass :: converter'變量)。 – DanielKO
我剛剛嘗試過,它也崩潰。 – markand
你不是在用'_static LuaConverters converters_'違反[** One Definition rule **](http://en.wikipedia.org/wiki/One_Definition_Rule)嗎?看看[這篇文章](http://stackoverflow.com/questions/3409034)例如 –