c ++ python API:PyImport_Import的第二次调用导致SIGSEGV

Arn*_*nox 6 c++ python numpy segmentation-fault

我试图通过c Api从c ++调用python来获取c ++中两个numpy Arrays的值.我第一次调用我的程序callPython()时,一切似乎运行正常,但第二次调用导致SIGSEGV

  pModule = PyImport_Import(pName);
Run Code Online (Sandbox Code Playgroud)

被执行.

flebool的答案中,有一个比我更简单的最小示例代码,具有相同的错误.

minimal.cpp

#include <Python.h>
#include <numpy/arrayobject.h>

long int geTuple( PyObject *pValue , PyObject *objI  , int i)
{
      objI = PyTuple_GetItem(pValue, i);

      long int n,M;
      double *xJ;

      if (objI != NULL) 
      {
          n = PyArray_NDIM(objI);
          printf("PyArray_NDIM(objI): %ld\n" , n );

          M = *PyArray_DIMS(objI);
          printf("PyArray_DIMS(objI) : %ld\n" , M );

          for (int k = 0; k < M; k++) 
          {
              xJ = (double *) PyArray_GETPTR1(objI, k );
              printf("xJ : %f\n" , *xJ );
          }
          return M;
      }
      else
      {
        printf("geTuple is Null \n");
        return -1;
      }
}

void callPython()
{
PyObject *pName, *pModule, *pFunc;
PyObject *pArgs, *pValue;

Py_Initialize();

//Import current folder to Python path
PyRun_SimpleString("import sys"); 
PyRun_SimpleString("sys.path.insert(0, '')");        

// Load name of pythonfile without py
pName = PyString_FromString( "minimal" );
/* Error checking of pName left out */

pModule = PyImport_Import(pName);
Py_DECREF(pName);

if (pModule != NULL) 
{
    //Name of the Python function
    pFunc = PyObject_GetAttrString(pModule, "minimalFunction" );
    /* pFunc is a new reference */

    if (pFunc && PyCallable_Check(pFunc)) 
    {
    pArgs = PyTuple_New(1);
    PyTuple_SetItem(pArgs, 0, PyInt_FromLong(2) );

    pValue =    PyObject_CallObject(pFunc, pArgs);

    Py_DECREF(pArgs);

    if (pValue != NULL)
    {
      long int dims[2];       
      PyObject *ob1,*ob2;

      dims[0] = geTuple( pValue , ob1  , 0);
      dims[1] = geTuple( pValue , ob2  , 1);

      Py_DECREF(pValue);
    }
    else 
    {
        Py_DECREF(pFunc);
        Py_DECREF(pModule);
        PyErr_Print();
        fprintf(stderr,"Call failed\n");
        return;
    }
    }
    else 
    {
    if (PyErr_Occurred())
        PyErr_Print();
    fprintf(stderr, "Cannot find function \"%s\"\n", "minimalFunction");
    }
    Py_XDECREF(pFunc);
    Py_DECREF(pModule);
}
else {
    PyErr_Print();
    fprintf(stderr, "Failed to load \"%s\"\n", "minimal.py");
    return ;
}
Py_Finalize();

}


int
main(int argc, char *argv[])
{
callPython();    

printf("2nd Call\n");
callPython();    

printf("Run over\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)

minimal.py

#! /usr/bin/env python
import numpy as np

def minimalFunction(dim):
xLower = np.ones(dim)
dCp = np.zeros(dim)

return xLower , dCp
Run Code Online (Sandbox Code Playgroud)

我使用python和numpy包以及anaconda使用以下命令在Ubuntu 12.04上编译我的程序:

gcc minimal.cpp -o minimal -I/usr/include/python2.7 -I/usr/include/python2.7 -lpython2.7 -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -Werror=format-security
Run Code Online (Sandbox Code Playgroud)

缩短的gdb回溯是

#101 0x00007ffff7a1ebeb in ?? () from /usr/lib/libpython2.7.so.1.0
#102 0x00007ffff79e972e in PyObject_CallFunction () from /usr/lib/libpython2.7.so.1.0
#103 0x00007ffff79b312d in PyImport_Import () from /usr/lib/libpython2.7.so.1.0
#104 0x0000000000400cea in callPython () at minimal.cpp:48
#105 0x0000000000400af8 in main (argc=<optimized out>, argv=<optimized out>) at minimal.cpp:110
Run Code Online (Sandbox Code Playgroud)

我对python的调用有什么问题?

gg3*_*349 2

这是评论,不是真正的答案。我不知道你的代码有什么问题。下面的(简单得多)示例也失败了。minimal.cpp:

#include <Python.h>

void callPython(){

    Py_Initialize();

    //Import current folder to Python path
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.insert(0, '')");

    // Load name of pythonfile without py
    PyObject *pName= PyString_FromString( "minimal" );
    /* Error checking of pName left out */

    PyObject *pModule= PyImport_Import(pName);
    Py_DECREF(pName);
    Py_DECREF(pModule);
    Py_Finalize();
}

int main(int argc, char *argv[])
{
    callPython();
    printf("2nd Call\n");
    callPython();
    printf("Run over\n");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

有了这个minimal.py

import numpy as np

def minimalFunction(dim):
    return 1
Run Code Online (Sandbox Code Playgroud)

有趣的是,如果您注释掉该import numpy语句,一切都会正常。

我试过:

  • 运行时python -m minimal && python -m minimal不会出现 shell 中的任何段错误,这排除了问题可能出现在 中的情况numpy,或者至少不只是出现在其中。
  • 在代码中sleep(2)的 2 个调用之间进行调用。无论如何它都会出现段错误。callPython()cpp

祝你好运!