How to use a C++ singleton to return an object initialized only once -
i real c++ noob, please patient me. first lets set stage.
i have c++ source in binary.cpp
compiles binary looks like:
# include "lotsofheaders.h" int main(int argc, char* argv[]) { int errorcode = foobar_global_unknown; // foobar instanciation foobar foobar(); // multiple calls :send_auth passing in foobar instance errorcode = send_auth(getx(), gety(), foobar); errorcode = send_auth(getx(), gety(), foobar); errorcode = send_auth(getx(), gety(), foobar); return errorcode == foobar_ok ? exit_success : exit_failure; }
the send_auth
method loaded object code file , gets passed instance of foobar. reason is, foobar comes api object not have source of , must not instantiated more once.
since main called once, works expected: there 1 instance of foobar , send_auth
can called multiple times.
the binary not of use me, need shared object library same. creates 1 instance of foobar , exposes external interface method send_with_auth
can called multiple times after shared object lib loaded.
my library code in library.cpp
looks this:
# include "lotsofheaders.h" # include "library.h" const char* send_with_auth(const char* x, const char* y){ std::string x(x); std::string y(y); int result = send_auth(x, y, 'some foobar singleton'); return true; }
since load shared object library via ruby ffi need c-style headers in library.h
lib:
extern "c" { const char* send_with_auth(const char* x, const char* y); }
now stage set have create instance of foobar once inside library , pass every call of send_auth
not memory violation error foobar.
here's (overly complex) attempt singleton understood it. there new library.h
so:
extern "c" { class singleton { private: static bool instanceflag; static singleton *single; singleton() { //private constructor } public: static foobar* fo; static singleton* getinstance(); ~singleton() { instanceflag = false; } }; const char* send_with_auth(const char* x, const char* y); }
and there implementation library.cpp
:
# include "lotsofheaders.h" # include "library.h" bool singleton::instanceflag = false; singleton* singleton::single = null; singleton* singleton::getinstance() { if(! instanceflag) { single = new singleton(); instanceflag = true; // bringing foobar instance once , once foobar fo; single->fo = &fo; return single; } else { return single; } } const char* send_with_auth(const char* x, const char* y){ std::string x(x); std::string y(y); singleton *single; single = singleton::getinstance(); int result = send_auth(x, y, *single->fo); return true; }
this code @ least compiles , can bind shared object library. when load library in external process (a ruby module using ruby ffi in case) error:
could not open library '/some/path/libfoobar.so': /some/path/libfoobar.so: undefined symbol: _zn9singleton2ere (loaderror)
i'm quite sure compiling/binding/stripping process library.o libfoobar.so ok, because succeeds in other cases. quite sure misunderstand c++'s singleton concept here. wonder how can achive goal: create 1 instance of foobar inside shared object library , pass every call of methods library exposes outside.
can on that? regards felix
update
using commandlineparser in library stupid. in fact returned 2 c-strings. api library path , log dir. recreated namespace:
namespace { char* home("/path/to/api/libs"); char* log("/tmp"); foobar foobar(home, log); }
that leads seg fault in moment when load library. in contrast can put these lines function directly:
const char* send_with_auth(const char* x, const char* y){ std::string x(x); std::string y(y); char* home("/path/to/api/libs"); char* log("/tmp"); foobar foobar(home, log); int result = send_auth(x, y, &foobar); return true; }
everything works fine here except fact second call send_with_auth
lets crash cause foobar instantiated again.
update 2:
finally solved simpler, used globally available bool switch initialize foobar instance once:
namespace baz{ bool foobarinitialized = false; } const char* send_with_auth(const char* certificatepath, const char* certificatepin, const char* xmldata){ std::string certificate_path(certificatepath); std::string certificate_pin(certificatepin); std::string xml_data(xmldata); foobar *foobar_ptr; if (! baz::foobarinitialized) { char* home_dir("/path/to/api/lib"); char* log_dir("/tmp"); foobar_ptr = new foobar(home_dir, log_dir); baz::foobarinitialized = true; } int result = send_auth(x, y, foobar_ptr); return xml_data.c_str(); }
now can call send_with_auth
endlessly without having foobar instantiated more once. done!
so first suggestion do
the simplest thing possibly work
and rid of singleton entirely. create global foobar object in library:
// library.cpp namespace { foobar global_foobar; }
i've put in anonymous namespace won't clash other symbol called "global_foobar" in main executable, or library.
this mean can accessed within library.cpp. if have more 1 .cpp file linked lib, you'll need marginally more elaborate:
// library_internal.h namespace my_unique_library_namespace { extern foobar global_foobar; } // library.cpp #include "library_internal.h" namespace my_unique_library_namespace { foobar global_foobar; } // library_2.cpp #include "library_internal.h" using my_unique_library_namespace::global_foobar;
Comments
Post a Comment