出于研究的原因,我试图将C和Python结合起来,但是我的代码中出现了问题。我使用了教程中的代码,但似乎获取python文件的代码不起作用。代码如下:
地狱杯.py
def sayHello(name):
return "Hello " + name + "!"
主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; }
最佳答案
这里没有足够的信息来给出完整的答案,但基本的问题几乎可以肯定的是helloClass.py
不会在模块搜索路径上的任何地方结束,因此PyImport_Import
找不到它。
例如,您可能正在将main
可执行文件构建到类似于~/Library/Developer/Xcode/DerivedData/Hello/Build/Products/Release/hello
的位置,但没有在那里复制helloClass.py
。或者,您可能正在复制它,但模块路径上没有等效的dirname $0
。或者……好吧,有一百万种可能性,但答案在任何情况下都是一样的:
找出可执行文件和Python文件的安装位置。
从这些知识中建立一条合适的(可能是相对的)路径。
确保将路径添加到模块路径。
Python如何搜索模块的具体细节在不同版本之间是不同的,但是基本思想在The import
statement中解释过(或者the 3.3 version,它遵从于The import system),而且通常只是在sys.path
中添加一些内容。
(请注意,如果您构建的是.app bundle,而不是Unix命令行可执行文件,则有一个标准答案:将.py文件放在标准位置,使用Cocoa或CoreFoundation api获取路径,然后使用该路径。但这似乎与此无关。)
查看您在https://github.com/Eduardof0nt/help.git上传的项目:
你不能在任何地方复制。你必须决定复制到哪里,这完全取决于你想如何部署。但出于调试的目的,为了获得可测试的东西,您可以将它放在helloClass.py
可执行文件旁边(在Hello Python!
或build/Debug
中)。要做到这一点:
在项目导航器中选择项目。
在显示的项目视图的左侧栏中选择目标。
选择构建阶段选项卡。
单击“添加生成阶段”按钮。
添加复制文件阶段。
将其目标设置为产品目录。
将build/Release
从项目导航器拖到构建阶段。
现在,当您构建时,如果您查看输出(打开“All”和“All Messages”),您将在“Link build/Debug/Hello Python!”后面看到“Copy build/Debug/helloClass.py!”。而且,如果您查看该目录,您将看到两个文件并排排列。
但这并不能解决你的全部问题。因为helloClass.py
不会出现在Python使用的/wherever/you/started/build/Debug
上。最快的方法是在sys.path
之前和Py_SetProgramName(argv[0])
之后调用Py_Initialize()
。对于您的用例来说,这可能不是正确的做法,但是您将阅读文档并理解所有这些操作的作用,因为我不可能解释在SO答案中嵌入Python的所有细节。
当你试图学习这些东西时,你可能想做一些调试。例如,您可以PySys_SetArgvEx(argc, argv, 1)
查看printf(path=%s\n", Py_GetPath())
等价物是什么,以及sys.path
查看PyObject_Print(mod, stdout, 0)
中的内容,等等。但实际上,您需要使用Xcode调试器添加一个断点,并在运行时尝试执行这些操作。
这在Extending and Emnbedding the Python Interpreter中有很多解释,您确实需要阅读它;没有替代品。(您不需要阅读整个Python/C API Reference Manual,但在完成之前,您最终将阅读大量的内容,并能够很好地搜索它。)然而,由于嵌入Python比扩展Python更不常见,因此文档实际上并不包含您所需的所有内容,因此…如果您正在使用的任何教程都不包括mod
和PySys_*
之类的内容,您可能会首先需要找到一个更好的教程。