1

I'm trying to wrap a C++ singleton with boost::python:

class EigenSolver {
    private:
        static EigenSolver* _self;
        static int _refCount;
    protected:
        EigenSolver();
        ~EigenSolver();

    private:
        EigenSolverOptions _options;
        BasicTypes::Array<double> eigenValues;
        BasicTypes::RegularArray <double> eigenVectors;

    public:
        // singleton initialization, returns unique instance
        static EigenSolver* Instance() {
            if (!_self) _self = new EigenSolver();
            return _self;
        }
        // singleton memory free
        void FreeInst() {
            _refCount--;
            if (!_refCount) {
                delete this;
                _self = NULL;
            }
        }
};

Wrapper code:

py::class_<EigenSolver, boost::shared_ptr<EigenSolver>, boost::noncopyable>
    ("EigenSolver", py::no_init)
    .def("Instance", &EigenSolver::Instance, py::return_internal_reference<>())

When I try to compile the library, I get an unresolved external symbol error:

error LNK2001: unresolved external symbol 
"private: static class UTILS::EigenSolver * UTILS::EigenSolver::_self" 
(?_self@EigenSolver@UTILS@@0PEAV12@EA)
PythonBindingsSolverLib.lib
What is the right way to wrap a C++ singleton class?

What is the right way to wrap a C++ singleton class using boost::python?

Thanks in advance, Ivan.

Ivan Gromov
  • 4,195
  • 9
  • 41
  • 57
  • 1
    Why the heck would that class be a singleton? –  Sep 20 '12 at 16:32
  • Why the heck would that be a class? –  Sep 20 '12 at 16:37
  • 1
    @delnan I'm not quite familiar with c++ singleton implementation, but why wouldn't it be? It has a static pointer that will be instantiated on the first Instance() call. – Ivan Gromov Sep 20 '12 at 16:42
  • @IvanGromov It is a singleton (as far as I can tell, I'm no C++ guru -- it definitely is an attempt at a singleton). What I don't grasp is why you'd *want* it to be a singleton. Why can't you just have a number of `EigenSolver`s? (Assuming it makes sense to have an object for that, as daknøk noted.) –  Sep 20 '12 at 16:45
  • @delnan It has to be a singleton because its constructor call MPI_init() method which can be called only once (I'm aware that using a singleton is this situation is rather a bad practice, but I will have to deal with lots of legacy code otherwise). – Ivan Gromov Sep 20 '12 at 16:50

1 Answers1

0

The problem was solved using the implementation provided in C++ Singleton design pattern question:

py::class_<EigenSolver, boost::shared_ptr<EigenSolver>, boost::noncopyable>
    ("EigenSolver", py::no_init)
    .add_property("instance", py::make_function(&EigenSolver::Instance, 
    py::return_value_policy<py::reference_existing_object>()))
;
Community
  • 1
  • 1
Ivan Gromov
  • 4,195
  • 9
  • 41
  • 57