On Fri, 21 Sep 2012 21:17:31 +0200, mathias.b...@gmx.de wrote: > On 21.09.2012, 16:28:20 Phil Thompson wrote: >> On Mon, 3 Sep 2012 22:27:41 +0200, mathias.b...@gmx.de wrote: >>> Hi Phil, >>> >>> I've come across a case which I think deserves its own function >> annotation. >>> This is the proplem: >>> >>> I'm embedding Python code into a C++ app. There are two wrapped classes: >>> >>> class Netlister >>> { >>> virtual ~Netlister(); >>> ... >>> }; >>> >>> and >>> >>> class Project >>> { >>> virtual ~Project(); >>> ... >>> virtual NetLister* netLister(const std::string& netListText) >> const; >>> }; >>> >>> In Python, I have ("ltse_app" is the C++ app exposed as module) >>> >>> >>> class LTspiceNetLister(ltse_app.NetLister): >>> ... >>> >>> and >>> >>> class Project(ltse_app.Project): >>> ... >>> def netLister(self, netListText): >>> return LTspiceNetLister() >>> >>> >>> First, I call a Python function which gives me an instance of the Python >>> class "Project". Then (in C++, using its wrapper), I call its method >>> "netLister", >>> which returns an instance of "LTspiceNetLister". The goal is to use >>> this instance on the C++ side via its wrapper. Thus, ownership should be >>> with C++. >>> >>> But there is no corresponding annotation for the sip file. I have to >>> provide >>> a "%VirtualCatcherCode": >>> >>> virtual NetLister* netLister(const std::string& netListText /NoCopy/) >>> const; >>> %VirtualCatcherCode >>> PyObject *resObj = sipCallMethod(0, sipMethod, "D", >>> const_cast<std::string*>(&a0), sipType_std_string, NULL); >>> sipIsErr = !resObj || sipParseResult(0, sipMethod, resObj, "H0", >>> sipType_NetLister, &sipRes) < 0; >>> if (!sipIsErr) sipTransferTo(resObj, Py_None); >>> Py_XDECREF(resObj); >>> %End >>> >>> Note how I use "sipTransferTo(resObj, Py_None);" to bind the Python >> object >>> to the C++ instance. >>> I'm basically asking for something like the "Factory" annotation which >>> does just that. >>> >>> "Factory" tells sip that a wrapped C++ function creates a new object >> that >>> will be owned by the >>> Python side. I'd like to have another annotation which tells sip that >> the >>> Python implementation >>> of a class method creates a new object that will be owned by the C++ >> side. > >> The documentation for /Factory/ is wrong (now fixed in hg). It >> effectively >> does... > >> sipTransferTo(resObj, selfObj); > >> ...in the virtual catcher (where selfObj) is the class's self object (the >> Project instance in this case).
This is wrong as well. It actually does... sipTransferTo(resObj, resObj); ...so effectively creating a reference cycle. >> You are using Py_None but I don't think it would make a difference. > >> Would this remove your use case for sipTransfer(obj, Py_None)? > >> Phil > > No it wouldn't. My embedding currently works like this: I have a .py file > which is imported as module at program start. This module defines a > factory function, which is called from C++ and returns an instance of > a Python class derived from a sip-wrapped C++ class ("Project"). The > PyObject* obtained this way is then fed into sip's "api_convert_to_type" > to get hold of the wrapper instance. This instance is then used in the > C++ code. It transparently forwards method calls to the Python part. > (That's why it was so important to have the wrapper "re-throw" Python > exceptions as C++ exceptions.) > Thanks to "sipTransfer(obj, Py_None)" I don't have to manually manage the > PyObject representing the Python part. It just gets automatically deleted > by the C++ wrapper. > > Further, your "sipTransferTo(resObj, selfObj);" above would bind the > returned > "NetLister" to the "Project" instance. But they are not related in terms > of life time. I only want the reference count of the Python part to be > decreased > by one when the C++ wrapper is destroyed. Provided there are no further > references on the Python side, this automatically destroys the Python > part, too. > > No parent-child relationships here like in Qt. Just Python objects that > can be > used in C++ as if they were C++ only. So I think you can use /Factory/ for what you want to do. However there are some problems and inconsistencies with the different Transfer annotations so I may well make further changes. Phil _______________________________________________ PyQt mailing list PyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt