How to embed python in an Objective-C OS X plugin application?

I am trying to use python in a new OS X application for plugin scripts. I am looking to offload some of the programming logic in python for easy, on-the-fly modification. I started by studying the Big Nerd Ranch Tutorial . This seemed to work, but he suggested an older Python binding method. It seems like with Xcode 5 we have to install python using this Mac developer library tech note . However, this process creates a linked python instance, not an embedded one. I tried to follow the recommendations in the answer to this question , but it seems to have broken.

So my question is this: what are the modern methods of creating python for use as a plugin environment in an Objective-C Mac OS X application? How to do this to make sure that it is associated with the application, and that you can install any additional libraries that may be required before the final Objective-C application is created?

+6
source share
1 answer

I came up with a method that seems to work quite well.

First download the source version of python that you want to use from the official site. Extract the archive somewhere. I am using Python 3.4.2. Adjust the commands in your system for the specific version that you are using.

Create the assembly directory that you will use for this version of python for development. The entire directory should not contain spaces to ensure that bash correctly interprets strings (#!). I used /Users/myaccount/development/python/devbuild/python3.4.2 .

Go to the extracted Python directory and run the following commands:

 ./configure --prefix="/Users/myaccount/development/python/devbuild/python3.4.2" make make install 

This will install python in the development directory. Configure the Python path to use the correct directory:

 export PYTHONPATH="/Users/myaccount/development/python/devbuild/python3.4.2/lib/python3.4/site-packages/" 

Go to the python bin directory ( /Users/myaccount/development/python/devbuild/python3.4.2/bin ) and use pip3 there to install any modules you need. The $PYTHONPATH parameter ensures that the modules are installed in the correct site-packages directory.

Find a convenient home for the PyObjC repository and clone it there. Then check the tag for the latest version and install it, making sure your $PYTHONPATH is still correct:

 hg clone https://bitbucket.org/ronaldoussoren/pyobjc cd pyobjc hg tags hg checkout [the id of the latest version from the tag list] /Users/myaccount/development/python/devbuild/python3.4.2/bin/python3 ./install.py 

Whenever you need to update python modules, just make sure you use the correct python python and $PYTHONPATH .

Now add python to your Xcode project.

Drag /Users/myaccount/development/python/devbuild/python3.4.2 into the Xcode project, setting it so that you don’t need to copy items if necessary, and create a link to the folder.

Add /Users/myaccount/development/python/devbuild/python3.4.2/include/python3.4m to the Header Search Paths setting in the Xcode Build Settings project. Not sure if there is a way to do this as a generalized step, just to find the directory specified in the directory we just added.

Drag the library `/Users/myaccount/development/python/devbuild/python3.4.2/lib/libpython3.4m.a to the Xcode project, setting it as a link without copying.

Now you can use the code from the scriptbook tutorial repository for beginners of the Nerd ranch with a few changes.

Plugin Manager code will require the NSString extension to work with wchar_t strings, which seem to be similar to the Python APIs:

 @interface NSString (WcharEncodedString) - (wchar_t*) getWideString; @end @implementation NSString (WcharEncodedString) - (wchar_t*) getWideString { const char* tmp = [self cStringUsingEncoding:NSUTF8StringEncoding]; unsigned long buflen = strlen(tmp) + 1; wchar_t* buffer = malloc(buflen * sizeof(wchar_t)); mbstowcs(buffer, tmp, buflen); return buffer; } @end 

The Python header should be included as follows:

 #include "Python.h" 

The following code must be run before Py_Initialize() is called in order to install the correct python, PYTHONPATH, and PYTHONHOME executable, as suggested by Zorg on this other issue.

 NSString* executablePath = [[NSBundle mainBundle] pathForResource:@"python3.4" ofType:nil inDirectory:@"python3.4.2/bin"]; Py_SetProgramName([executablePath getWideString]); NSString* pythonDirectory = [[NSBundle mainBundle] pathForResource:@"python3.4" ofType:nil inDirectory:@"python3.4.2/lib"]; Py_SetPath([pythonDirectory getWideString]); Py_SetPythonHome([pythonDirectory getWideString]); 

Finally, the python path must be extended in the PluginExecutor.py file to include various subdirectories of the high-level lib path. Add the following code to the top of the Plugin Executor file:

 import sys from os import walk path = sys.path.copy() for p in path: for root,dirs,files in walk(p): if p is not root: sys.path.append(root) 

I will post updates if everything starts to break down, but for now this seems like a working solution.

+10
source

Source: https://habr.com/ru/post/977495/


All Articles