"Jörg Sauer" <joerg2k1 at yahoo.de> wrote in message news:3ae3d7f5.3475467 at news.t-online.de... > Hi folks, > I've got the following problem exposing a c++ singleton pattern to [snip] > What is going wrong??? Hard to say, since the "sample code" you include can't be the one you're using -- for example this snippet: > public: > static CObRegistry& Init() > CObRegistry& GetReg(); would not compile, as it's not syntactically correct C++ code. (At least a semicolon is missing, perhaps another 'static' as well -- it's hard to guess exactly what IS your code, and probably not all that important). Presumably, the key issue is that a copy constructor gets invoked under the covers. It's hard to avoid that: in general, it's VERY hard work to wrap/expose/handle non-canonical C++ objects (ones that can't be default-constructed, destructed, copied, assigned). Not just in/to Python or in/to Boost Python specifically: non canonical objects are Bad News in any substantial C++ system. The good news is that you do NOT need to wrap/expose non canonical objects. A more reliable, flexible, sounder pattern is to wrap and expose "lightweight proxy" C++ objects -- that will internally delegate whatever is needed to your "one and only substantial object", but will NOT implement the singleton Design Pattern with the attendant efforts to ensure only one of them is ever subject to instantiation (whence the need to avoid copying, etc, etc, and hence the non-canonicality). > It seems that the python c++ wrapper instantiate 2 different singleton > objects. The static member keeps constant and the constructor is > called only one time, but how can I get two singleton objects then? Copy constructor appears to be the likeliest culprit. But if you forbid copy-constructing, the exposing will probably fail, so that is likely to be a dead-end. Don't waste effort trying to expose non-canonical objects: it's better to spend lesser effort exposing canonical objects and keep issues such as "there must be only one instance of this" to the INTERNALS of your system. > What I want to get is that every call to GetReg() gets the same c++ > object and that python calls like reg1.setObject(40); > reg2.setObject(10); change the same c++ memory thow it doesn't matter > through which. Python object I store or retrieve date. You can get the part from "and that" onwards by giving up the strict letter of the first line of this paragraph -- let a thousand C++ objects bloom as long as each one is a very lightweight thingy that just delegates everything (specifically all of its state) to the "real" singly-instantiated object (which then doesn't need to implement the Singleton DP any more). > Any suggestions? Over the last week or so, the singleton DP came up for discussion a couple of times on this group -- I seem to be in a tiny minority in disliking it intensely in favour of featherweight proxies, though I know I'm NOT the only one since I recall a C++ Report article that made points very similar to mine. www.google.com/groups should let you fetch and read the few relevant articles for background. Leaving your sample code alone (assuming needed changes are made so it will compile), say it comes from a C++ library you want to wrap and NOT modify, I would suggest a few changes as follows: > ------ Sample Code ---------- > > > #include <iostream> > #include <string> > using std::cout; > using std::endl; > > > #include <boost/python/class_builder.hpp> > namespace python = boost::python; > > > namespace mein{ // Avoid cluttering the global namespace. > > class CObRegistry // Singleton class > { > // Singleton > private: > static CObRegistry* m_pObRegistry; protected: > CObRegistry(); > public: > static CObRegistry& Init() > CObRegistry& GetReg(); I assume GetReg is a _static_ function of CObRegistry. > // My functions > protected: > int m_TestObj; > public: > int getObject(); > void setObject(int); > }; [snip] Add the following for example: struct CObRegistryFeatherweightProxy { int getObject() { return CObRegistry::GetReg().getObject(); } void setObject(int i) { CObRegistry::GetReg().setObject(i); } }; CObRegistryFeatherweightProxy GetRegProxy() { return CObRegistryFeatherweightProxy(); } Now the expose-to-Python part: > // Create the Python type object for our extension class. > python::class_builder<CObRegistry> CObRegistry_class(this_module, > "ObRegistry"); becomes python::class_builder<CObRegistryFeatherweightProxy> CObRegistry_class etc; > //Add memberfunctions of myObj_class,singleton_class > CObRegistry_class.def(&CObRegistry::getObject, "getObject"); > CObRegistry_class.def(&CObRegistry::setObject, "setObject"); > CObRegistry_class.def(&CObRegistry::Init, "Init"); remove the third one of these and change the other two to use methods from CObRegistryFeatherweightProxy -- I don't think you need to expose the Init as it's called from within GetReg, but, if you want, you can wrap that into another function anyway. > //Add normal function > this_module.def(GetReg,"GetReg"); This too wouldn't compile I think, but anyway it now becomes this_module.def(GetRegProxy, "GetReg"); and does compile since GetRegProxy is a global function (in your sample it seems to me CObRegistry::GetReg would have been needed here, else the code shouldn't compile, surely). I haven't tested this exact set of mods, but, anyway, this general approach has long served me well any time I've had to wrap and expose C++ classes, even just from one subsystem to another when both coded in C++, much more when such things as COM or Python or other cross-language passages were involved. I _strongly_ suggest you expose canonical stateless objects rather than "fighting City Hall" by striving to expose non-canonical objects at any subsystem interface! Alex
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4