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_authlets 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

Popular posts from this blog

php - get table cell data from and place a copy in another table -

javascript - Mootools wait with Fx.Morph start -

php - Navigate throught databse rows -