用Cython包装c++api时的“访问冲突读取位置”

2024-09-30 06:33:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用Python开发一个用c++编写的api的包装器模块。api本身是本地安装在我的计算机上的Windows(7)应用程序的c库/api的包装器。我可以访问c++api源代码,但不能访问c库。我用python2.7.5(即vs9.0)中的distutils构建Cython模块,还尝试了3.4.1(即vs10.0)这两个32位的安装。在

当访问该模块时,会出现一个弹出窗口,说明python.exe has stopped working,然后按close时Process finished with exit code -1073741819 (0xC0000005)。调试时(我有visualstudio2012),我得到:Unhandled exception at 0x64ED1EB2 (apiclient10m.dll) in python.exe: 0xC0000005: Access violation reading location 0x7C03B776。我有时也会得到Unhandled exception at 0x1E0EFECF (python27.dll) in python.exe: 0xC0000005: Access violation writing location 0x5753422C.,这取决于我如何调用api。在

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

它看起来是这样的:

我的模块.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)

getuid方法是失败的方法。在

c++api:

^{pr2}$

当显示一个窗口用于登录应用程序时,连接部分可以正常工作。失败的是get_baseline_uid。 部分c api h文件:

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

h文件与一堆静态库(.lib文件)一起驻留在指定给distutilsC:\Program Files (x86)\App\api的目录中。这些库似乎访问C:\Program Files (x86)\App\prog文件夹中的dll文件。这就是导致访问冲突的dll apiclient10m.dll所在的位置。在

地区设置.py:

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")

Tags: 模块instancefromapiuidgetconnectioncpp

热门问题