&引用;访问冲突读取位置“;包装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文件)一起驻留在为distutilsC:\Program Files(x86)\App\api
指定的目录中。这些库似乎可以访问C:\ProgramFiles(x86)\App\prog
文件夹中的dll文件。这是导致访问冲突的dllapiclient10m.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)代码>