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

Popular posts from this blog

c# - Send Image in Json : 400 Bad request -

jquery - Fancybox - apply a function to several elements -

An easy way to program an Android keyboard layout app -