Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Boost python, exposing meyers singleton

I want to do it in a right way. I've seen exposing boost::serialization::singleton here Boost python export singleton but I don't want to use that. I want to use simple meyers singleton instead.

This code below works, but documentation says that using http://www.boost.org/doc/libs/1_43_0/libs/python/doc/v2/reference_existing_object.html#reference_existing_object-spec/ is dangerous.

Code:

class Singleton 
{
private:
Singleton(){};

public:
static Singleton & getInstance()
{
    static Singleton instance;
    return instance;
}

int getNumber() { return 5; }
};

And in module:

class_<Singleton>("singleton", no_init)
    .def("getInstance", &Singleton::getInstance, return_value_policy<reference_existing_object>()).staticmethod("getInstance")
    .def("getNumber", &Singleton::getNumber)

    ;

What is good way to do it? Using return_internal_reference<>() resulted in error while executing python code.

like image 326
Marek Avatar asked Oct 07 '22 18:10

Marek


1 Answers

We have many such things in our code, I haven't thought about an easy way, but we expose them by returning boost::shared_ptr<> from the references with a null deleter (we have somehow moved parts of our code to shared_ptr and others not, so this is a mixture). This is quite not the nicest thing to do, but it works as expected and has not pitfals, if you ensure not to do anything with the pointer after the main has been left.

The lifetime of your object will overlive the interpreter, so you need not have to fear any problems while passing any references back to python here. The library will only released after the interpreter has exit (maybe with calling or without calling your destructors, there may be sometimes a whole in case of errors or so.). So you can think of the interpreter as a classical main() function in this case.

class_<XY, shared_ptr<XY>, boost::noncopyable >("XY",no_init)
  .def("getInstance",&XY::getSharedInstance )
  .staticmethod("getInstance")

struct NullDeleter
{
  void operator()(const void*){}
};

XY& XY::getInstance()
{
  static XY in;
  return in;
}

// This can also be written as a standalone function and added to the python class above.
shared_ptr<XY> XY::getSharedInstance()
{
  return shared_ptr<XY>( &getInstance(), NullDeleter() );
}

Or you can write the sharedInstance non intrusive to a separate function and use this in the python package:

shared_ptr<XY> getSharedInstance()
{
  return shared_ptr<XY>( &XY::getInstance(), NullDeleter() );
}

class_<XY, shared_ptr<XY>, boost::noncopyable >("XY",no_init)
  .def("getInstance",&getSharedInstance )
  .staticmethod("getInstance")
like image 197
Sven Avatar answered Oct 10 '22 10:10

Sven