[Pythonmac-SIG] PyObjC vs "old school" embedding

Ronald Oussoren ronaldoussoren at mac.com
Wed Jun 1 07:18:31 CEST 2005


On 31-mei-2005, at 22:17, gandreas at gandreas.com wrote:

> So PyOXIDE is based on the traditional way to embed python in an  
> application (explicitly calling the python APIs to access and call  
> stuff), and this worked reasonably well.  For example, it runs  
> various scripts at startup, which register various callbacks to  
> handle things like new documents, new interactives, etc... (and  
> then the underlying Objective C code explicitly calls these  
> callbacks at appropriate points).
>
> Unfortunately, things recently have gone downhill (with either  the  
> Tiger system framework or the 2.4 unofficial official framework,  
> with PyObjC 1.3.5(*)).  I've got an "interactive" window (i.e., the  
> interactive shell) which is loaded via a menu command - in the  
> window's controller awakenFromNib: I've got the  following code:
> - (void) awakeFromNib
> {
>     NSLog(@"Interactive awakeFromNib");
>     myMain = PyImport_AddModule("__main__");
>     if (myMain == NULL || (PyErr_Occurred())) {
>     //NSLog(@"Couldn't add module __main__");
>     PyErr_Print();
>     }
> (... and then the code that calls the python code to hook the  
> interactive window to the text view, etc...)
>
>
> Now, when the interactive window is created by the menu, everything  
> works fine (application main loop calls the Objective C code which  
> loads a nib, nib loading calls above routine, everything fine).  If  
> the same thing includes a layer of python on the stack, such as is  
> done as part of the debugger (since I've got interactive windows in  
> the debugger so you can directly access/execute code in your  
> debugged context), it fails - namely, PyImport_AddModule crashes:
>
> #0  0x100a68d8 in PyImport_AddModule (name=0x159c8 "__main__") at / 
> Users/bob/src/Python-2.4.1/Python/import.c:308
> #1  0x000090bc in -[PyInteractive awakeFromNib] (self=0x54b71a0,  
> _cmd=0x909f36ac) at /Volumes/YWork1/PyOXIDE/Source/PyInteractive.mm: 
> 132
> #2  0x92886788 in -[NSSet makeObjectsPerformSelector:] ()
> #3  0x93636f94 in -[NSIBObjectData  
> nibInstantiateWithOwner:topLevelObjects:] ()
> #4  0x9370dbdc in old_loadNib ()
> [snip]
> #8  0x9370d6a4 in -[NSWindowController window] ()
> #9  0x007d7a98 in ffi_call_DARWIN ()
> #10 0x007d74b0 in ffi_call ()
> #11 0x007beb24 in PyObjCFFI_Caller ()
> #12 0x007d1e3c in PyObjCAPI_Register ()
> #13 0x1000c348 in PyObject_Call (func=0x0, arg=0x101158b4,  
> kw=0x101268b8) at /Users/bob/src/Python-2.4.1/Objects/abstract.c:1751
> [snip]
> #39 0x100092cc in PyObject_CallMethod (o=0x0, name=0x10119178 "a  
> more convenient interface.", format=0x713030 "") at /Users/bob/src/ 
> Python-2.4.1/Objects/abstract.c:1751
> #40 0x0000d954 in -[NSDocument(NSDocumentPyHandler)  
> pythonOnHandler:] (self=0x4cef190, _cmd=0x1746c, sender=0x387220)  
> at /Volumes/YWork1/PyOXIDE/Source/NSDocumentPyHandler.mm:181
> #41 0x936be08c in -[NSApplication sendAction:to:from:] ()
> [snip]
>
> Basically, the app calls my object to handle the menu command  
> ("Debug") which calls PyObject_CallMethod  to handle the "bound  
> menu routine".  That python code does a bunch of stuff, loads a  
> nib, the nib loading fires off my awakeFromNib code, which tries to  
> get the __main__ module, and boom!
>
> Looking at import.c:308:
>
> PyObject *
> PyImport_GetModuleDict(void)
> {
>     PyInterpreterState *interp = PyThreadState_GET()->interp; //  
> Crash is here, since PyThreadState_GET is NULL
>     if (interp->modules == NULL)
>         Py_FatalError("PyImport_GetModuleDict: no module  
> dictionary!");
>     return interp->modules;
> }
>
>
> There are no python threads running, I've not called  
> PyEval_InitThreads() or anything like that.  So it _appears_ that  
> any code called from Python through the Objective C bridge can no  
> longer access the interpreter - is this correct?  What would be the  
> approach to allow this to work? Should I initialize threads  
> support, and execute all my callbacks on a separate thread?  Or  
> would I need to create a new interpreter state for these?  Or am I  
> just plain hosed on mixing "traditional" embedding techniques with  
> PyObjC?

PyObjC gives up the GIL before calling into ObjC. This is necesary to  
make it possible to use python from multiple threads. You should use  
the API in PEP311 to acquire the GIL before you starting using the  
Python API and release it again when you're done.

Ronald

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 2105 bytes
Desc: not available
Url : http://mail.python.org/pipermail/pythonmac-sig/attachments/20050601/30c81d10/smime.bin


More information about the Pythonmac-SIG mailing list