Cython设置外部变量导致访问冲突

时间:2015-09-23 16:07:22

标签: python dll cython

我正在尝试使用cython来包装外部库。外部库的部分接口要求我设置从dll导出的外部变量的成员,但是我收到了访问冲突错误:

  

处理完成,退出代码为-1073741819(0xC0000005)

我正在使用Cython和Python 2.7以及来自http://www.microsoft.com/en-us/download/details.aspx?id=44266的编译器套件。一切都在使用setuptools进行编译和链接。

以下.pyx代码包含问题:

import numpy as np
cimport numpy as cnp

ctypedef float real32_T

ctypedef struct ExtU_ST_TopLevel_MWL_T:
    real32_T GroundSpeed

cdef extern from 'ST_TopLevel_MWL.h':

    void ST_TopLevel_MWL_initialize()
    void ST_TopLevel_MWL_step()
    void ST_TopLevel_MWL_terminate()

    ExtU_ST_TopLevel_MWL_T ST_TopLevel_MWL_U


def ST_TopLevel_MWL_batch_run(cnp.ndarray[cnp.double_t, ndim=1, mode='c'] ground_speed not None):
    global ST_TopLevel_MWL_U
    ST_TopLevel_MWL_initialize()
    print('0x%x' % <unsigned long long>&ST_TopLevel_MWL_U)
    print('0x%x' % <unsigned long long>&ST_TopLevel_MWL_U.GroundSpeed)
    print('%f' % ST_TopLevel_MWL_U.GroundSpeed)
    # The following line results in the access violation
    ST_TopLevel_MWL_U.GroundSpeed = <float>0.0
    print('%f' % ST_TopLevel_MWL_U.GroundSpeed)
    ST_TopLevel_MWL_terminate()

ST_TopLevel_MWL_U.GroundSpeed = <float>0.0行会导致访问冲突。如果我删除该行,我不会获得访问冲突,但是,当然,如果我无法设置此变量,则无法使用该数据库。

我相信setuptools是静态链接一个负责动态加载dll(.dll)的库(.lib),但是它的机制对我来说是完全隐藏的,所以我找不到根本原因

我正在尝试与之交互的dll是使用'ert_shrlib.tlc'目标和'Microsoft Windows SDK v7.1 |来自Matlab Simulink嵌入式编码器生成和构建的。 nmake(64位Windows)'工具链。

1 个答案:

答案 0 :(得分:0)

问题是头文件&#39; ST_TopLevel_MWL.h&#39;不使用__declspec(dllimport)

为dll导入声明变量

msdn article提供了足够的细节来解释它。这是一段摘录:

  

&#34;但是,您必须使用__declspec(dllimport)才能导入DLL中使用的变量。&#34;

Matlab Simulink嵌入式编码器&#39; ert_shrlib.tlc&#39; target使用.DEF文件来公开导出的过程和变量。它在头文件中直接使用extern ExtU_ST_TopLevel_MWL_T ST_TopLevel_MWL_U;。当用于编译dll的相同头文件也用于导入端的编译时,缺少的__declspec(dllimport)会导致构建的代码在杂草中的某处引用幻像变量而不是导出的变量来自dll。这会导致访问冲突崩溃。

编辑头文件以替换&#34; extern&#34;用&#34; extern __declspec(dllimport)&#34;解决了这个问题。

这是另一个有用的链接,它解释了Matlab Central的问题:How do I call a DLL created from Simulink model in a Visual Studio application?