如何将python嵌入到ObjectiveC OS X应用程序中?

2024-06-17 19:02:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试在一个新的osx应用程序中使用python编写插件脚本。我希望将一些程序逻辑卸载到python中,以便于实时修改。我从看Big Nerd Ranch tutorial开始。这似乎是可行的,但它提出了一种旧的连接Python的方法。从Xcode5开始,我们应该使用this Mac Developer Library Tech Note安装python。然而,这个过程似乎创建了一个链接的python实例,而不是一个嵌入式实例。我尝试过遵循answer to this question中的指导原则,但似乎失败了。在

所以我的问题是:在ObjectiveC MacOSX应用程序中构建python作为插件运行时的最佳实践是什么?如何确保它与应用程序捆绑在一起,并且在最终的Objective C应用程序构建之前,可以安装任何附加的库呢?在


Tags: 实例方法脚本插件应用程序developermacthis
1条回答
网友
1楼 · 发布于 2024-06-17 19:02:56

我想出了一个似乎效果不错的方法。在

首先,从official website下载要使用的python版本的源代码。从某处提取档案。我使用的是python3.4.2。根据所使用的特定版本调整系统上的命令。在

创建一个用于开发python版本的构建目录。整个目录中不应该有空格,以确保bash解释she-bang(#!)线路正确。我用了/Users/myaccount/development/python/devbuild/python3.4.2。在

进入解压的Python目录并运行以下命令:

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

这将在开发构建目录中安装python。设置Python路径以使用正确的目录:

^{pr2}$

进入python bin目录(/Users/myaccount/development/python/devbuild/python3.4.2/bin)并使用那里的pip3安装所需的任何模块。$PYTHONPATH设置将确保模块安装到正确的site-packages目录中。在

为PyObjC存储库找到一个方便的家并在那里克隆它。然后签出最新版本标记并安装它,确保您的$PYTHONPATH仍然正确:

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

无论何时需要更新python模块,只要确保使用正确的python bin和$PYTHONPATH。在

现在将python添加到Xcode项目中。在

/Users/myaccount/development/python/devbuild/python3.4.2目录拖到Xcode项目中,将其设置为不根据需要复制项,并创建一个文件夹引用。在

/Users/myaccount/development/python/devbuild/python3.4.2/include/python3.4m添加到Xcode项目的Build Settings中的Header Search Paths设置中。不确定是否有一种方法可以作为一个通用步骤来搜索我们刚刚添加的文件夹引用目录。在

将`/Users/myaccount/development/python/devbuild/python3.4.2/lib/libpython3.4m.a库拖动到Xcode项目中,将其设置为添加为引用而不进行复制。在

来自Big Nerd Ranch scripting tutorial repository的代码现在只需稍作修改就可以使用了。在

插件管理器代码需要一个NSString扩展来处理wchar_t字符串,Python API似乎非常喜欢这些字符串:

@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

Python头应该包括如下内容:

#include "Python.h"

在调用Py_Initialize()之前,需要运行以下代码,以便按照Zorg对另一个问题的建议设置正确的python可执行文件PYTHONPATH和PYTHONHOME。在

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]);

最后,python路径需要在PluginExecutor.py文件中展开,以包含高级lib路径的各个子目录。将以下代码添加到插件执行器文件的顶部:

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)

如果问题开始出现问题,我会发布更新,但目前看来这是一个有效的解决方案。在

相关问题 更多 >