我有一个我正在嵌入python的应用程序。它是在Windows上开发的,它工作正常,但是现在我将它移植到linux,而在Py_Initialize()中崩溃的成功率较低。从gdb开始,它似乎在加载os模块时发生。
gdb在seg fault上报告这个callstack:
#0 0x002384fc in import_submodule (mod=None, subname=0xb7d8a9bb "os", fullname=0xb7d8a9bb "os") at ../Python/import.c:2551
#1 0x0023893c in load_next (mod=<value optimized out>, altmod=<value optimized out>, p_name=0xb7d8a9ac, buf=0xb7d8a9bb "os", p_buflen=0xb7d8a9b4) at ../Python/import.c:2411
//.... etc...:
#65 0x002439de in Py_Initialize () at ../Python/pythonrun.c:361
Python / import.c中的import_submodule源代码(从2.6.5 python下载):
static PyObject *
import_submodule(PyObject *mod, char *subname, char *fullname)
{ //***************** THIS IS LINE 2551***************************
PyObject *modules = PyImport_GetModuleDict();
PyObject *m = NULL;
/* Require:
if mod == None: subname == fullname
else: mod.__name__ + "." + subname == fullname
*/
if ((m = PyDict_GetItemString(modules, fullname)) != NULL) {
Py_INCREF(m);
}
else {
PyObject *path, *loader = NULL;
char buf[MAXPATHLEN+1];
struct filedescr *fdp;
FILE *fp = NULL;
if (mod == Py_None)
path = NULL;
else {
path = PyObject_GetAttrString(mod, "__path__");
if (path == NULL) {
PyErr_Clear();
Py_INCREF(Py_None);
return Py_None;
}
}
buf[0] = '\0';
fdp = find_module(fullname, subname, path, buf, MAXPATHLEN+1,
&fp, &loader);
Py_XDECREF(path);
if (fdp == NULL) {
if (!PyErr_ExceptionMatches(PyExc_ImportError))
return NULL;
PyErr_Clear();
Py_INCREF(Py_None);
return Py_None;
}
m = load_module(fullname, fp, buf, fdp->type, loader);
Py_XDECREF(loader);
if (fp)
fclose(fp);
if (!add_submodule(mod, m, fullname, subname, modules)) {
Py_XDECREF(m);
m = NULL;
}
}
return m;
}
反汇编+部分来源+断点:
2550 import_submodule(PyObject *mod, char *subname, char *fullname)
2551 {
0x002384f0 <+0>: push %ebp
0x002384f1 <+1>: mov %esp,%ebp
0x002384f3 <+3>: sub $0x1058,%esp
0x002384f9 <+9>: mov %ebx,-0xc(%ebp)
=> 0x002384fc <+12>: call 0x174787 <__i686.get_pc_thunk.bx>
0x00238501 <+17>: add $0x112af3,%ebx
0x00238507 <+23>: mov %esi,-0x8(%ebp)
0x0023850a <+26>: mov 0x8(%ebp),%esi
0x0023850d <+29>: mov %edi,-0x4(%ebp)
0x00238510 <+32>: mov %eax,-0x102c(%ebp)
0x00238516 <+38>: mov %edx,-0x1030(%ebp)
0x0023851c <+44>: mov %gs:0x14,%eax
这里发生了什么?显然,libpython2.6.so中的一些代码已加载并运行。
答案 0 :(得分:2)
在调用Py_Initialize之前,尝试使用Py_SetPythonHome设置Python home。从硬编码的完整路径开始到python目录。还要确保你没有混合调试&amp;发布版本。 Py_GetPath是一个很好的API,可以看到所有python在哪里寻找模块 - 但不知道它是否可以在Py_Initialize之前调用。
char pySearchPath[] = "/users/abc/Python26";
Py_SetPythonHome(pySearchPath);
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print 'Today is',ctime(time())\n");
cerr << Py_GetPath() << endl;