c++ - Static libraries and shared objects, are symbols shared? -
i'm creating helper create multiple inheritance between c++ classes , lua objects. because lua store c/c++ user objects void *, it's hard safe casts when retrieve objects.
for instance,
if have
class { } class b { } class c : public a, public b { }
and pass object of type c lua, pass address of c instance, when need cast b, c++ compiler automatically align pointer position of b in c , thus, it's not safe cast void * pointer c b directly.
to avoid issue, use kind of converter. in lua, objects contains name string, when need cast object type other type, uses converter this:
converters["b"]["c"](mypointer, myresultpointer);
this class helps creating these converters :
// 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); }; } };
this class compiled static library used many times in project.
object need passed shared_ptr (it solve problem of ownership , deletion). works well, however, segfaults when using static libraries.
then, have simple module battery, compiled shared object , links common library.
for scope of example, not contains functions, use 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; }
this compiled shared object named battery.so, lua use dlopen() , dlcose() load it.
finally, main. links common , use create objects.
// 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); // dlopen() , 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; }
to summary:
- common.cpp, common.h compiled simple static library (libcommon.a)
- main.cpp, compiled , links libcommon.a
- battery.cpp, compiled shared object , links libcommon.a
the main segfaults @ exit, core file says it's in destructor of std::function<> guess called multiple times on same pointer, it?
is static library data shared in code? how can avoid issue?
the begin of core
#0 0x0000000000404062 in std::__1::function<void (void*, void*)>::~function() () #1 0x0000000000404025 in std::__1::function<void (void*, void*)>::~function() ()
the next trace unreadable , unusable.
the code , global/static data of static library injected each module links it. case, there multiple luaeclass::converters
instances exist in project. , need call luaopen_battery()
in each module links static library.
i not sure if crash has static link, quite sure went complicated implementation.
the first issue want address safely converting void*
a*, b*, c*
. class/interface want export lua? if it's class c
, can define below methods in class c:
void pushthis(lua_state *l); static c* getthis(lua_state *l, int idx);
both methods use c*
, don't need convert function. can use meta table distinguish pointers other userdata. if need b*
, just:
b* b = (b*)c::getthis(l, idx);
and may not need shared_ptr. shared_ptr doesn't on deleting c++ object when lua object collected gc(because shared_ptr still exist in heap). instead, have implement __gc
callback in meta table delete object.
Comments
Post a Comment