从Objective-C调用Python

4 投票
3 回答
4396 浏览
提问于 2025-04-15 16:13

bbum在StackOverflow上发了一些关于如何实现这个的基本步骤,但我不太清楚具体细节。Python代码应该放在哪里?我的Objective-C代码又怎么才能知道这些Python代码呢?如果我在命令行上编译的话,该怎么做呢?

3 个回答

0

谷歌是你的好帮手。搜索“Cocoa Python”这个词,很快就找到了PyObjc这个链接。

3

目前,通过PyObjC在Objective-C应用程序中使用Python的情况并不是很好。py2app是和PyObjC一起提供的工具,它可以编译可加载的包(也就是可以通过NSBundle加载的东西),这看起来是最好的方法:在Python中定义一个NSObject的子类,并实现一个你在Objective-C中定义的协议(可以通过objc.protocolNamed获取),然后通过py2app将这个Python文件编译成一个可加载的包(py2app使用标准的setup.py)。不幸的是,py2app并没有得到很好的维护,特别是插件(可加载包)目标,在10.5版本左右引入了一个严重的内存泄漏问题,导致从py2app编译的包中传递的数据在从Python到Objective-C时会泄漏。真让人头疼。

PyObjC会根据在Python中执行的与Objective-C相关的代码来操作Objective-C的运行时环境,因此要从Objective-C调用Python代码,一般的步骤是:

  1. 为Python代码编写一个PyObjC的包装器
  2. 执行代码,声明这个PyObjC包装器,以将这些定义添加到Objective-C的运行时环境中
  3. 从Objective-C调用PyObjC包装器。因为它是在运行时声明的,所以在编译时无法使用这些符号,因此你需要使用NSClassFromString等方法来实例化这个类。声明一个@protocol并包含适当的方法会很有帮助,这样Objective-C编译器就不会抱怨缺少方法。

如果你有灵活性,最好的选择是使用Cocoa-Python应用模板(也就是创建一个Python应用),然后从Python中加载你的Objective-C代码作为可加载的包。这样可以帮你管理Python解释器。

否则,在Cocoa-Python应用模板的main.m中,你应该能够创建一个Python解释器,执行你的PyObjC代码,然后继续进行。显然,解释器需要保持运行,以便你的Python代码可以执行,所以你可能需要在一个单独的线程中进行这个操作。可以看出,这样做可能会有点复杂。还是建议使用上面提到的Python应用。

请记住,PyObjC并不保证能与Objective-C的垃圾回收器良好配合,因此所有这些选项都要求你的Objective-C代码不使用垃圾回收。

12

这里有个来源:

从Objective-C调用Python

我在我的博客上发布了一个详细的说明,讲解如何做到这一点,因为这个内容比我在这里能写的要长很多。

简单来说,就是:使用一个抽象类来提供必要的类型信息,这样C编译器就能满意,同时也提供了桥接所需的元数据。

撰写回答