如何在Xcode中将Python函数导入C?
我正在尝试把C语言和Python结合起来做研究,但我的代码出现了一些问题。我用了一个教程里的代码,但似乎获取Python文件的代码不太好使。以下是代码:
helloClass.py
def sayHello(name):
return "Hello " + name + "!"
main.c
int main(int argc, const char * argv[]) {
char name[50];
printf("What's your name?\n");
fgets(name, 64, stdin);
char *answer = NULL;
PyObject *modname, *mod, *mdict, *func, *stringarg, *args, *rslt;
Py_Initialize();
PySys_SetPath(Py_GetPath());
modname = PyString_FromString("helloClass");
mod = PyImport_Import(modname);// Here mod = null because it can´t find it.
if (mod){
mdict = PyModule_GetDict(mod);
func = PyDict_GetItemString(mdict, "sayHello");
if (func){
if (PyCallable_Check(func)) {
stringarg = PyString_FromString(name);
args = PyTuple_New(1);
PyTuple_SetItem(args, 0, stringarg);
rslt = PyObject_CallObject(func, args);
if (rslt) {
answer = PyString_AsString(rslt);
Py_XDECREF(rslt);
}
Py_XDECREF(stringarg);
Py_XDECREF(args);
}
Py_XDECREF(mdict);
Py_XDECREF(func);
}
Py_XDECREF(modname);
Py_XDECREF(mod);
}
printf("%s", answer);
answer = NULL; }
1 个回答
这里的信息不够详细,无法给出完整的答案,但基本问题几乎肯定是 helloClass.py
没有出现在模块搜索路径上,所以 PyImport_Import
找不到它。
举个例子,可能你把 main
可执行文件放在了像 ~/Library/Developer/Xcode/DerivedData/Hello/Build/Products/Release/hello
这样的地方,但没有把 helloClass.py
复制到那里。或者,可能你确实把它复制过去了,但 dirname $0
的结果不在你的模块路径上。还有很多其他可能性,但每种情况的答案都是一样的:
找出可执行文件和 Python 文件被安装到哪里。
根据这些信息构建一个合适的(可能是相对的)路径。
确保这个路径被添加到模块路径中。
Python 搜索模块的具体细节在不同版本之间有所不同,但基本思路可以在 import 语句(或者 3.3 版本,它又参考了 导入系统)中找到,通常只需要在 sys.path
中添加一些东西。
(注意,如果你构建的是 .app 包而不是简单的 Unix 命令行可执行文件,有一个标准的解决方案——你把 .py 文件放在一个标准位置,使用 Cocoa 或 CoreFoundation API 获取路径,然后使用这个路径。但这似乎在这里不太相关。)
看看你上传的项目 https://github.com/Eduardof0nt/help.git:
你没有把 helloClass.py
复制到任何地方。你需要决定 要把它复制到哪里,这完全取决于你想如何部署它。但为了调试方便,想要得到一个可以测试的东西,你可以把它放在 Hello Python!
可执行文件旁边(在 build/Debug
或 build/Release
中)。具体操作如下:
- 在项目导航器中选择项目。
- 在出现的项目视图左侧边栏中选择目标。
- 选择构建阶段标签。
- 点击添加构建阶段按钮。
- 添加一个复制文件阶段。
- 将目标设置为产品目录。
- 把
helloClass.py
从项目导航器拖到构建阶段中。
现在,当你构建时,如果查看输出(打开“所有”和“所有消息”),你会看到“复制 build/Debug/helloClass.py”紧接在“链接 build/Debug/Hello Python!”之后。如果你查看那个目录,会看到这两个文件并排放着。
但这并不能解决你所有的问题。因为 /wherever/you/started/build/Debug
不会在 Python 使用的 sys.path
中。解决这个问题的最快方法是在 Py_Initialize()
之前调用 Py_SetProgramName(argv[0])
,然后在之后调用 PySys_SetArgvEx(argc, argv, 1)
。这可能不适合你的使用场景,但你需要阅读文档,了解这些操作的具体作用,因为我无法在 StackOverflow 的回答中解释所有嵌入 Python 的细节。
在你学习这些内容时,可能需要进行一些调试。例如,你可以使用 printf(path=%s\n", Py_GetPath())
来查看 sys.path
的内容,使用 PyObject_Print(mod, stdout, 0)
来查看 mod
中的内容,等等。但实际上,你会想使用 Xcode 调试器——设置一个断点,尝试在运行时进行这些操作。
很多内容在 扩展和嵌入 Python 解释器 中有解释,你确实需要阅读这些;没有替代品。(你不需要阅读整个 Python/C API 参考手册,但你最终会阅读很多内容,并在完成之前熟练搜索它。)然而,由于嵌入 Python 比扩展它要少见得多,文档中并没有包含你需要的所有内容,所以……如果你使用的教程没有涵盖 PySys_*
和 Py_GetPath
之类的内容,你可能需要先找到一个更好的教程。