Re: [Pyobjc-dev] Proper way to expose custom Obj-C classes to Python?
Brought to you by:
ronaldoussoren
|
From: Ian M. <ip...@po...> - 2014-02-19 14:05:11
|
Ken & Georg,
Thanks for your replies.
I've already gotten this far -- i.e. I'm running the interpreter in
process, executing arbitrary python scripts in it, and trading objects back
and forth via NSClassFromString and other API with provided wrappers. What
I was hoping to achieve was "first-class" support for my classes -- like
the framework wrappers that ship with PyObjC for the system frameworks.
I've made some progress by brute force. I've gotten objective-metadata-tool
installed, and I'm currently working through getting it to scan my
framework's headers. This process appears under-documented, so my
experience is basically, "Try an invocation of objective-metadata-tool in
the debugger. See what fails. Figure out why it failed. Adjust invocation
to avoid that condition. Repeat." I'll report back with my findings if I
have any eventual success.
Thanks,
Ian
On Wed, Feb 19, 2014 at 2:56 AM, Ken Thomases <ke...@co...> wrote:
> On Feb 18, 2014, at 5:23 PM, Ian McCullough wrote:
>
> > I'm trying to determine the best way to expose custom,
> > application-specific, non-system-framework (i.e. not in one of the
> > framework wrappers provided with PyObjC) classes written in Objective-C
> to
> > python across the PyObjC bridge. My eventual hope is to develop a
> "hybrid"
> > application in which some portions of the app are in Objective-C and
> others
> > are in python, with the two side integrating via the PyObjC bridge. Most
> of
> > the documentation I've been able to find seems to focus on situations
> where
> > the goal is to have all the app-specific code be in python, and to have
> the
> > python call out to AppKit classes, etc via the bridge and the
> pre-packaged
> > system framework wrappers.
> >
> > I've not seen any indication that it's possible to expose classes from an
> > app.
>
> It is. I don't know if this is the best way, but one way is to link an
> otherwise ordinary Cocoa app, written in Objective-C, to the Python
> framework. You would then use the Python embedding API to set up the
> Python runtime and load and run some Python code. You might do something
> like:
>
> NSString* pythonPath = /* path within your app bundle to its Python
> files */;
> setenv("PYTHONPATH", [pythonPath fileSystemRepresentation], 1);
>
> Py_SetProgramName("/usr/bin/python2.6"); // or whatever version of
> Python you link against; don't know how relevant this is
> Py_InitializeEx(0);
> PyEval_InitThreads();
> PyGILState_STATE gilState = PyGILState_Ensure();
>
> NSString* script = /* path to a initialization script in your app
> bundle */;
> static char* arg0 = strdup([script fileSystemRepresentation]); //
> don't deallocate until Python runtime is terminated, if ever
> static char** argv = &arg0; // ditto
> PySys_SetArgv(1, argv);
>
> FILE* scriptFile = fopen([script fileSystemRepresentation], "r");
> int result = PyRun_SimpleFileEx(scriptFile, (char *)[[script
> lastPathComponent] fileSystemRepresentation], 1);
> if (result) /* handle error */;
>
> PyGILState_Release(gilState);
> if (gilState == PyGILState_LOCKED)
> {
> PyThreadState_Swap(NULL);
> PyEval_ReleaseLock();
> }
>
> The script file mentioned above would just import modules and do
> initialization and then exit. It wouldn't be a long-running script. Since
> the application keeps running and the Python runtime is persistent, the
> state which is set up by the script persists, too.
>
> After that, you have a few ways of interacting between the Python code and
> the Objective-C code. Any Python class which inherits from a Cocoa class
> is registered with the Objective-C runtime. It can be looked up with
> NSClassFromString(). Then, it's methods can be invoked directly. You can
> make that simpler by declaring Objective-C interfaces for those classes.
>
> The Objective-C code can pass its objects into the methods of the Python
> classes and the Python code can then operate on those objects.
>
> Also, the Python code can find some objects itself, such as NSApp or
> various singletons. It can then do things like set itself as delegates or
> register for notifications.
>
> I believe that the classes of your app, since they were registered with
> the Objective-C runtime at the time that Python was loaded and your
> initialization script was run, can just be used directly in your Python
> scripts. If that doesn't work, I'm sure you can use
> Foundation.NSClassFromString() to get access.
>
> I hope that helps.
>
> Cheers,
> Ken
>
>
|