&引用;访问冲突读取位置“;包装c+时+;带Cython的api 我在Python中使用一个包装器,用C++编写的API。api本身是本地安装在我的计算机上的Windows(7)应用程序的c库/api的包装器。我可以访问C++ API源代码而不是C库。我使用Python 2.7.5(即VS 9.0)中的distutils构建Cython模块,并尝试了3.4.1(即VS 10.0)两种32位安装

&引用;访问冲突读取位置“;包装c+时+;带Cython的api 我在Python中使用一个包装器,用C++编写的API。api本身是本地安装在我的计算机上的Windows(7)应用程序的c库/api的包装器。我可以访问C++ API源代码而不是C库。我使用Python 2.7.5(即VS 9.0)中的distutils构建Cython模块,并尝试了3.4.1(即VS 10.0)两种32位安装,python,c++,c,dll,cython,Python,C++,C,Dll,Cython,访问模块时出现的情况是,弹出窗口显示python.exe已停止工作,然后按close时进程结束,退出代码为-1073741819(0xC0000005)。调试时(我使用Visual Studio 2012),我在python.exe中的0x64ED1EB2(apiclient10m.dll)处得到:未处理的异常:0xC0000005:访问冲突读取位置0x7C03B776。有时,我还会在python.exe中的0x1E0EFECF(python27.dll)处获得未处理的异常:0xC0000005

访问模块时出现的情况是,弹出窗口显示
python.exe已停止工作
,然后按close时
进程结束,退出代码为-1073741819(0xC0000005)
。调试时(我使用Visual Studio 2012),我在python.exe中的0x64ED1EB2(apiclient10m.dll)处得到:
未处理的异常:0xC0000005:访问冲突读取位置0x7C03B776
。有时,我还会在python.exe中的0x1E0EFECF(python27.dll)处获得
未处理的异常:0xC0000005:访问冲突写入位置0x5753422C。
这取决于我调用api的方式

我认为它与C++中定义的对象“Objistt”相关,并被发送到C库进行更新。然后用C++读取这个对象,然后将INT发送回Cython。当返回某个内存位置时,调用堆栈中的某个地方存在不允许的访问

这就是它看起来的样子:

mymodule.pyx:

# distutils: language = c++
# distutils: extra_compile_args = ["/EHsc"]
# distutils: sources = [connection.cpp, object.cpp]
# distutils: include_dirs=['C:\\Program Files (x86)\\App\\api']
# distutils: library_dirs=['C:\\Program Files (x86)\\App\\api']

from libcpp.string cimport string
from cython.operator cimport dereference as deref

cdef extern from "connection.h" namespace "pvcs":

    cdef cppclass connection:
        connection() except +
        ...

cdef class PyConnection:

    cdef connection *_cpp_connection_instance    # Pointer to wrapped connection instance

    def __cinit__(self):
        self._cpp_connection_instance = new connection()

    def __dealloc__(self):
        del self._cpp_connection_instance

cdef extern from "object.h" namespace "pvcs":

    cdef int get_baseline_uid(connection c, string spec)

def get_uid(PyConnection connection, bytes specification):
    return get_baseline_uid(
        deref(connection._cpp_connection_instance), specification)
namespace pvcs {
  class connection {
    public:
      connection();
      ~connection();

  int get_baseline_uid(connection & c, std::string & spec) {
    ObjStruct os = { 0 };

    //Fills the struct os with the information
    if(InitSpec(c.uid(), const_cast<char *>(spec.c_str()), BASELINE, &os) == 1) {
      int uid = os.uid;
      ObjFree(&os);
      return uid;  // Somewhere after this point the error occurs.
    }
    return -1;
  }
typedef struct ObjStruct
{
    int         uid;
    int         objType;
    int         typeUid;
    _TCHAR      typeName[(L_TYPE_NAME + 1)*CHARSIZEMAX];
    _TCHAR      productId[(L_PRODUCT_ID + 1)*CHARSIZEMAX];
    _TCHAR      objId[(MAX_L_ID + 1)*CHARSIZEMAX];
    _TCHAR      variant[(L_VARIANT + 1)*CHARSIZEMAX];
    _TCHAR      revision[(L_REVISION + 1)*CHARSIZEMAX];
    _TCHAR      description[(L_DESCRIPTION + 1)*CHARSIZEMAX];
    _TCHAR      userName[(L_USER + 1)*CHARSIZEMAX];
    _TCHAR      status[(L_STATUS + 1)*CHARSIZEMAX];
    _TCHAR      dateTime[(L_DATE_TIME + 1)*CHARSIZEMAX];
    _TCHAR      isExtracted;
    int         noAttrs;        /* The number of attributes for this object. */
    ObjAttrStruct *attrs;   /* Pointer to the array of attributes. */
    int         specUid;
}   ObjStruct;

extern int APIFUN CCONV InitSpec(int, _TCHAR*, int, PcmsObjStruct*);
from distutils.core import setup
from Cython.Build import cythonize

METADATA = {'name': 'mymodule', 
            'ext_modules': cythonize("mymodule.pyx"),}

if __name__ == '__main__':
    metadata = METADATA.copy()
    setup(**metadata)
get_uid方法是失败的方法

c++api:

# distutils: language = c++
# distutils: extra_compile_args = ["/EHsc"]
# distutils: sources = [connection.cpp, object.cpp]
# distutils: include_dirs=['C:\\Program Files (x86)\\App\\api']
# distutils: library_dirs=['C:\\Program Files (x86)\\App\\api']

from libcpp.string cimport string
from cython.operator cimport dereference as deref

cdef extern from "connection.h" namespace "pvcs":

    cdef cppclass connection:
        connection() except +
        ...

cdef class PyConnection:

    cdef connection *_cpp_connection_instance    # Pointer to wrapped connection instance

    def __cinit__(self):
        self._cpp_connection_instance = new connection()

    def __dealloc__(self):
        del self._cpp_connection_instance

cdef extern from "object.h" namespace "pvcs":

    cdef int get_baseline_uid(connection c, string spec)

def get_uid(PyConnection connection, bytes specification):
    return get_baseline_uid(
        deref(connection._cpp_connection_instance), specification)
namespace pvcs {
  class connection {
    public:
      connection();
      ~connection();

  int get_baseline_uid(connection & c, std::string & spec) {
    ObjStruct os = { 0 };

    //Fills the struct os with the information
    if(InitSpec(c.uid(), const_cast<char *>(spec.c_str()), BASELINE, &os) == 1) {
      int uid = os.uid;
      ObjFree(&os);
      return uid;  // Somewhere after this point the error occurs.
    }
    return -1;
  }
typedef struct ObjStruct
{
    int         uid;
    int         objType;
    int         typeUid;
    _TCHAR      typeName[(L_TYPE_NAME + 1)*CHARSIZEMAX];
    _TCHAR      productId[(L_PRODUCT_ID + 1)*CHARSIZEMAX];
    _TCHAR      objId[(MAX_L_ID + 1)*CHARSIZEMAX];
    _TCHAR      variant[(L_VARIANT + 1)*CHARSIZEMAX];
    _TCHAR      revision[(L_REVISION + 1)*CHARSIZEMAX];
    _TCHAR      description[(L_DESCRIPTION + 1)*CHARSIZEMAX];
    _TCHAR      userName[(L_USER + 1)*CHARSIZEMAX];
    _TCHAR      status[(L_STATUS + 1)*CHARSIZEMAX];
    _TCHAR      dateTime[(L_DATE_TIME + 1)*CHARSIZEMAX];
    _TCHAR      isExtracted;
    int         noAttrs;        /* The number of attributes for this object. */
    ObjAttrStruct *attrs;   /* Pointer to the array of attributes. */
    int         specUid;
}   ObjStruct;

extern int APIFUN CCONV InitSpec(int, _TCHAR*, int, PcmsObjStruct*);
from distutils.core import setup
from Cython.Build import cythonize

METADATA = {'name': 'mymodule', 
            'ext_modules': cythonize("mymodule.pyx"),}

if __name__ == '__main__':
    metadata = METADATA.copy()
    setup(**metadata)
h文件与一组静态库(.lib文件)一起驻留在为distutils
C:\Program Files(x86)\App\api
指定的目录中。这些库似乎可以访问
C:\ProgramFiles(x86)\App\prog
文件夹中的dll文件。这是导致访问冲突的dll
apiclient10m.dll
所在位置

distutils setup.py:

# distutils: language = c++
# distutils: extra_compile_args = ["/EHsc"]
# distutils: sources = [connection.cpp, object.cpp]
# distutils: include_dirs=['C:\\Program Files (x86)\\App\\api']
# distutils: library_dirs=['C:\\Program Files (x86)\\App\\api']

from libcpp.string cimport string
from cython.operator cimport dereference as deref

cdef extern from "connection.h" namespace "pvcs":

    cdef cppclass connection:
        connection() except +
        ...

cdef class PyConnection:

    cdef connection *_cpp_connection_instance    # Pointer to wrapped connection instance

    def __cinit__(self):
        self._cpp_connection_instance = new connection()

    def __dealloc__(self):
        del self._cpp_connection_instance

cdef extern from "object.h" namespace "pvcs":

    cdef int get_baseline_uid(connection c, string spec)

def get_uid(PyConnection connection, bytes specification):
    return get_baseline_uid(
        deref(connection._cpp_connection_instance), specification)
namespace pvcs {
  class connection {
    public:
      connection();
      ~connection();

  int get_baseline_uid(connection & c, std::string & spec) {
    ObjStruct os = { 0 };

    //Fills the struct os with the information
    if(InitSpec(c.uid(), const_cast<char *>(spec.c_str()), BASELINE, &os) == 1) {
      int uid = os.uid;
      ObjFree(&os);
      return uid;  // Somewhere after this point the error occurs.
    }
    return -1;
  }
typedef struct ObjStruct
{
    int         uid;
    int         objType;
    int         typeUid;
    _TCHAR      typeName[(L_TYPE_NAME + 1)*CHARSIZEMAX];
    _TCHAR      productId[(L_PRODUCT_ID + 1)*CHARSIZEMAX];
    _TCHAR      objId[(MAX_L_ID + 1)*CHARSIZEMAX];
    _TCHAR      variant[(L_VARIANT + 1)*CHARSIZEMAX];
    _TCHAR      revision[(L_REVISION + 1)*CHARSIZEMAX];
    _TCHAR      description[(L_DESCRIPTION + 1)*CHARSIZEMAX];
    _TCHAR      userName[(L_USER + 1)*CHARSIZEMAX];
    _TCHAR      status[(L_STATUS + 1)*CHARSIZEMAX];
    _TCHAR      dateTime[(L_DATE_TIME + 1)*CHARSIZEMAX];
    _TCHAR      isExtracted;
    int         noAttrs;        /* The number of attributes for this object. */
    ObjAttrStruct *attrs;   /* Pointer to the array of attributes. */
    int         specUid;
}   ObjStruct;

extern int APIFUN CCONV InitSpec(int, _TCHAR*, int, PcmsObjStruct*);
from distutils.core import setup
from Cython.Build import cythonize

METADATA = {'name': 'mymodule', 
            'ext_modules': cythonize("mymodule.pyx"),}

if __name__ == '__main__':
    metadata = METADATA.copy()
    setup(**metadata)
一切编译和链接都很好,但在运行时,例如,根据我上面的解释,它在最后一行失败:

import mymodule
con = mymodule.PyConnection()
uid = mymodule.get_uid(con, "item specification")

const\u cast(spec.c\u str())
看起来很恐怖。如果该函数正在以任何方式修改它所指向的内容,那么程序行为是未定义的。@Bathsheba将其替换为
itemid
,根据以下构造,它并没有解决访问冲突:
char itemid[PCMS\u L\u ID+1]={'\0'};strncpy(itemid,spec.c_str(),PCMS_L_ID)