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

Cython setting external variable causes access violation

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

Process finished with exit code -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 行导致访问冲突。如果删除该行,我不会遇到访问冲突,但是,当然,如果我无法设置此变量,我将无法使用该 dll。

我相信 setuptools 正在静态链接一个负责动态加载 dll (.dll) 的库 (.lib),但我完全不知道它的机制,所以我很难找到根本原因。

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

问题是头文件'ST_TopLevel_MWL.h'没有声明使用__declspec(dllimport)

导入dll的变量

一个msdn article给出了足够的细节来解释它。以下是摘录:

"However, you must use __declspec(dllimport) in order to import variables used in a DLL."

Matlab Simulink Embedded Coder 'ert_shrlib.tlc' 目标使用 .DEF 文件公开导出的过程和变量。它在头文件中直接使用 extern ExtU_ST_TopLevel_MWL_T ST_TopLevel_MWL_U;。当用于编译 dll 的同一个头文件也用于事物的导入端的编译时,缺少的 __declspec(dllimport) 会导致构建的代码引用杂草中某处的幻像变量而不是导出的变量从 dll。这会导致访问冲突崩溃。

编辑头文件,将“extern”替换为“extern __declspec(dllimport)”即可解决问题。

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