Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Python C API调用C函数两次时出现分段错误_Python_C_Python 2.7 - Fatal编程技术网

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

使用Python C API调用C函数两次时出现分段错误,python,c,python-2.7,Python,C,Python 2.7,最近,我想使用C包装器从Fortran(请参阅)调用Python。下面我发布一个更简单的例子。函数的第二次调用导致pModule=PyImport\u Import(pName)处出现分段错误。我发现问题出在scipy.optimizeimport newton的行上-如果我对它进行注释,一切都会正常工作。有没有办法解决这个问题 rootC.c #include "rootC.h" #include <Python.h> void root_(double* A, double*

最近,我想使用C包装器从Fortran(请参阅)调用Python。下面我发布一个更简单的例子。函数的第二次调用导致
pModule=PyImport\u Import(pName)
处出现分段错误。我发现问题出在scipy.optimizeimport newton的
行上-如果我对它进行注释,一切都会正常工作。有没有办法解决这个问题

rootC.c

#include "rootC.h"
#include <Python.h>

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();
}
#include "rootC.h"
#include <stdio.h>

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;
}
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 <Python.h>

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();
}
#include "rootC.h"
#include <stdio.h>

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;
}
#包括“rootC.h”
#包括
int main()
{
双A=0.4,B=0.3,t=0.1,x=0.0;
根(A、B、t和x);
printf(“x=%.15f\n”,x);
根(A、B、t和x);
printf(“x=%.15f\n”,x);
返回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
CC=gcc
FC=gfortran
CFLAGS=-I/usr/include/python2.7
LFLAGS=-L/usr/local/lib-lpython2.7-lm
.骗子:都是干净的
全部:主要
main:main.o rootC.o
$(CC)$^-o$@$(LFLAGS)
main.o:main.c
$(CC)$(CFLAGS)-c$<-o$@
rootC.o:rootC.c
$(CC)$(CFLAGS)-c$<-o$@
清洁:
rm-f*.o

问题在于每次调用函数时都要初始化和完成python shell。(它多次尝试初始化.dll)

编辑:

这是我的解决方案。。。(不是工作的最佳代码) 在你的主要演讲中

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;
}
然后在你的根C.h

void root_(double*, double*, double*, double*,bool*);
然后在rootC.c

#include "rootC.h"
#include <Python.h>

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();
    }
}
#包括“rootC.h”
#包括
无效根(双*A,双*B,双*t,双*x,布尔*停止)
{
PyObject*pName、*pModule、*pFunc;
PyObject*pArgs,*pValue,*sys,*path;
如果(*停止==错误)
{
Py_初始化();
}
sys=PyImport_ImportModule(“sys”);
path=PyObject_GetAttrString(sys,“path”);
PyList_Append(路径,PyString_FromString(“.”);
pName=PyString_FromString(“rootPY”);
pModule=PyImport\u Import(pName);
if(!pModule)
{
PyErr_Print();
printf(“pModule中的错误\n”);
出口(1);
}
pFunc=PyObject_GetAttrString(pModule,“root”);
pArgs=PyTuple_New(3);
PyTuple_SetItem(pArgs,0,PyFloat_FromDouble(*A));
PyTuple_SetItem(pArgs,1,PyFloat_from double(*B));
PyTuple_SetItem(pArgs,2,PyFloat_from double(*t));
pValue=PyObject_CallObject(pFunc,pArgs);
*x=PyFloat_AsDouble(pValue);
如果(*停止==真)
{
Py_Finalize();
}
}

这应该有用:)

一个人也可以这样做:

#include "rootC.h"
#include <Python.h>
#include <stdlib.h>

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

    ....
}
#包括“rootC.h”
#包括
#包括
无效初始化()
{ 
Py_初始化();
}
作废定稿()
{
Py_Finalize();
}
空根(双*A,双*B,双*t,双*x)
{
PyObject*pName、*pModule、*pFunc;
PyObject*pArgs,*pValue,*sys,*path;
静态int-i;
如果(i==0)
{   
++一,;
初始化();
脱欧(最终确定);
}
....
}

为什么要调用
PyImport\u Import
而不是像调用其他模块那样调用
PyImport\u Module
?另外,我会检查返回指针的函数是否为
NULL
,除非文档明确指出它不能为
NULL
,但是仍然存在相同的问题,而且在我得到结果之前,它在第二次调用期间挂起了一点。我看到您的标志中没有启用警告,为什么?它们可以帮助你发现(每个人都犯的)愚蠢的错误。将
-Wall-Wextra-Werror
添加到您的
CFLAGS
中,看看它是否有帮助。如前所述,
numpy
不喜欢初始化两次。这显示了
Stop
变量的替代方法。你真的需要通过引用通过
Stop
吗?我想以上就是我在凌晨3点以后写代码时发生的事情