使用Python C API调用C函数两次时的分段错误

最近我想使用C包装器从Fortran调用Python(见这里 )。 下面我发布一个更简单的例子。 函数的第二次调用导致pModule = PyImport_Import(pName)处的分段错误。 我发现问题是from scipy.optimize import newton线 – 如果我评论它一切正常。 任何想法如何解决它?

rootC.c

 #include "rootC.h" #include  void root_(double* A, double* B, double* t, double* x) { PyObject *pName, *pModule, *pFunc; PyObject *pArgs, *pValue, *sys, *path; Py_Initialize(); sys = PyImport_ImportModule("sys"); path = PyObject_GetAttrString(sys, "path"); PyList_Append(path, PyString_FromString(".")); pName = PyString_FromString("rootPY"); pModule = PyImport_Import(pName); if (!pModule) { PyErr_Print(); printf("ERROR in pModule\n"); exit(1); } pFunc = PyObject_GetAttrString(pModule, "root"); pArgs = PyTuple_New(3); PyTuple_SetItem(pArgs, 0, PyFloat_FromDouble((*A))); PyTuple_SetItem(pArgs, 1, PyFloat_FromDouble((*B))); PyTuple_SetItem(pArgs, 2, PyFloat_FromDouble((*t))); pValue = PyObject_CallObject(pFunc, pArgs); *x = PyFloat_AsDouble(pValue); Py_Finalize(); } 

rootC.h

 #ifndef ROOT_H_ #define ROOT_H_ void root_(double*, double*, double*, double*); #endif 

rootPY.py

 from mpmath import polylog, exp from scipy.optimize import newton def root(A,B,t): return 1 

main.c中

 #include "rootC.h" #include  int main() { double A = 0.4, B = 0.3, t = 0.1, x = 0.0; root_(&A,&B,&t,&x); printf("x = %.15f\n", x); root_(&A,&B,&t,&x); printf("x = %.15f\n", x); return 0; } 

Makefile文件

 CC = gcc FC = gfortran CFLAGS = -I/usr/include/python2.7 LFLAGS = -L/usr/local/lib -lpython2.7 -lm .PHONY: all clean all: main main: main.o rootC.o $(CC) $^ -o $@ $(LFLAGS) main.o: main.c $(CC) $(CFLAGS) -c $< -o $@ rootC.o: rootC.c $(CC) $(CFLAGS) -c $< -o $@ clean: rm -f *.o 

人们也可以这样做:

 #include "rootC.h" #include  #include  void Initialize () { Py_Initialize(); } void Finalize () { Py_Finalize(); } void root_(double* A, double* B, double* t, double* x) { PyObject *pName, *pModule, *pFunc; PyObject *pArgs, *pValue, *sys, *path; static int i; if (i == 0) { ++i; Initialize(); atexit(Finalize); } .... } 

问题是每次调用函数时初始化和完成python shell。 (它试图不止一次初始化.dll)

编辑: 链接到资源

这是我在main.c中的修复…(不是作业的最佳代码)

 int main() { double A = 0.4, B = 0.3, t = 0.1, x = 0.0; bool Stop = false; root_(&A,&B,&t,&x,&Stop); printf("x = %.15f\n", x); Stop=true; root_(&A,&B,&t,&x,&Stop); printf("x = %.15f\n", x); return 0; } 

然后在你的rootC.h中

 void root_(double*, double*, double*, double*,bool*); 

然后在rootC.c中

 #include "rootC.h" #include  void root_(double* A, double* B, double* t, double* x,bool* Stop) { PyObject *pName, *pModule, *pFunc; PyObject *pArgs, *pValue, *sys, *path; if (*Stop==false) { Py_Initialize(); } sys = PyImport_ImportModule("sys"); path = PyObject_GetAttrString(sys, "path"); PyList_Append(path, PyString_FromString(".")); pName = PyString_FromString("rootPY"); pModule = PyImport_Import(pName); if (!pModule) { PyErr_Print(); printf("ERROR in pModule\n"); exit(1); } pFunc = PyObject_GetAttrString(pModule, "root"); pArgs = PyTuple_New(3); PyTuple_SetItem(pArgs, 0, PyFloat_FromDouble((*A))); PyTuple_SetItem(pArgs, 1, PyFloat_FromDouble((*B))); PyTuple_SetItem(pArgs, 2, PyFloat_FromDouble((*t))); pValue = PyObject_CallObject(pFunc, pArgs); *x = PyFloat_AsDouble(pValue); if (*Stop==true) { Py_Finalize(); } } 

这应该工作:)