来自 dll 的运行函数的访问冲突

Posted

技术标签:

【中文标题】来自 dll 的运行函数的访问冲突【英文标题】:Access violation on run function from dll 【发布时间】:2009-10-27 15:48:44 【问题描述】:

我有 DLL,C++ 接口可以与他一起工作。在 bcb 中,msvc 可以正常工作。我想使用 Python 脚本来访问这个库中的函数。 使用 Swig 生成 python 包。

文件setup.py

 import distutils
 from distutils.core import setup, Extension

 setup(name = "DCM",
     version = "1.3.2",
     ext_modules = [Extension("_dcm", ["dcm.i"], swig_opts=["-c++","-D__stdcall"])],
     y_modules = ['dcm'])

文件dcm.i

%module dcm
%include <windows.i>

%
#include <windows.h>
#include "../interface/DcmInterface.h"
#include "../interface/DcmFactory.h"
#include "../interface/DcmEnumerations.h"
%

%include "../interface/DcmEnumerations.h"
%include "../interface/DcmInterface.h"
%include "../interface/DcmFactory.h"

运行这些命令(python 与扩展名 .py 相关联)

setup build
setup install

使用这个 DLL

import dcm

f = dcm.Factory() #ok

r = f.getRegistrationMessage() #ok
print "r.GetLength() ", r.GetLength() #ok
r.SetLength(0) #access violation

在最后一个字符串我得到访问冲突。而且我使用输入参数对每个函数都有访问冲突。

DcmInterface.h(接口)

class IRegistrationMessage

public:
...
    virtual int GetLength() const = 0;
    virtual void SetLength(int value) = 0;
...
;

uRegistrationMessage.cpp(在 DLL 中实现)

class TRegistrationMessage : public IRegistrationMessage

public:
...
virtual int GetLength() const
    
        return FLength;
    
    virtual void SetLength(int Value)
    
        FLength = Value;
        FLengthExists = true;
    
...
;

工厂

DcmFactory.h(在客户端代码中使用 DLL)

class Factory

private:
    GetRegistrationMessageFnc GetRegistration;

bool loadLibrary(const char *dllFileName = "dcmDLL.dll" )
    
    ...
        hDLL = LoadLibrary(dllFileName);
        if (!hDLL) return false;
        ...
        GetRegistration = (GetRegistrationMessageFnc) GetProcAddress( hDLL, "getRegistration" );
        ...
    
public:
Factory(const char* dllFileName = "dcmDLL.dll")

    loadLibrary(dllFileName);


IRegistrationMessage* getRegistrationMessage()
    
        if(!GetRegistration) return 0;
        return GetRegistration();
    ;
;

【问题讨论】:

也许您可以添加从生成的代码中调用Factory::SetLength() 的行和来自DcmFactory.h 的原始声明? ... arg1 = reinterpret_cast(argp1); ecode2 = SWIG_AsVal_int(obj1, &val2); if (!SWIG_IsOK(ecode2)) SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "IRegistrationMessage_SetLength" "', 参数 ""2"" 类型为 '" "int""'"); arg2 = static_cast(val2); (arg1)->SetLength(arg2); ... 【参考方案1】:

我发现了错误。 如果您使用 DLL,则必须以如下显式形式编写调用约定:

class IRegistrationMessage

public:
...
    virtual int _cdecl GetLength() const = 0;
    virtual void _cdecl SetLength(int value) = 0;
...
;

我附加了调用约定,现在一切正常。

【讨论】:

以上是关于来自 dll 的运行函数的访问冲突的主要内容,如果未能解决你的问题,请参考以下文章

运行使用 /clr 构建的 DLL 的本机 C++ 应用程序时访问冲突

视觉泄漏检测器在 ntdll.dll 上抛出“访问冲突读取位置”

使用 DLL 函数时的访问冲突异常

尝试运行非常简单的程序时访问冲突

javafx 致命错误异常访问冲突(问题框架:jfxmedia.dll)

从 Delphi“访问冲突”正确调用 DLL 中的 C++ 函数