Search code examples
pythonobjective-cnsbundle

Calling Python code from Objective-C


I am looking for the best way to call Python code from Objective-C program. Few details:

  • Python's code doesn't use PyObjC at all, just Python's basics.
  • There are several Python's files with similar functionality each (aka “variations on a theme”).

NSBundle

Encapsulating each *.py into *.bundle was the first thing that has came into mind.

PythonClass.py:

import objc
NSObject = objc.lookUpClass('NSObject')

class PythonClass(NSObject):
    def Function(self):
        print("Python is speaking!")

setup.py:

from distutils.core import setup
import py2app

setup(
    plugin = ['PythonClass.py'],
)

Terminal command: python setup.py py2app -s -p objc

It works fine, but there are several problems:

  • Large *.bundle size. Even though Foundation is not imported, and bundle is semi standalone (flag "-s"), the size of the *.bundle is ~1MB. Is there any other way to reduce the size?
  • PyObjC dependance. Class doesn't use objc, but if we don't subclass NSObject then, on Objective-C side, [bundle principalClass] is (Null) and PythonClass cannot be instantiated. Is there a way to avoid using NSObject in *.py?

CFBundle

I have also been thinking about using CFBundle, but CFBundleGetFunctionPointerForName(...) always returns NULL (of course, in this case, *.py contains a function, not a class). I couldn't find any material on this matter. Maybe some of you are more lucky.

Is there a better way of embedding Python into Objective-C?


Solution

  • Use Python/C API (a bridge between Python and C), C++ class (OOP layer for easier management) that calls Python code, and this method to put C++ class into CFBundle.

    If necessary, this also works with Dynamic Library (*.dylib) instead of CFBundle.