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). 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. Best Regards, Mathias Born _______________________________________________ PyQt mailing list PyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt