【问题标题】:Wrapper for native functions本机函数的包装器
【发布时间】:2016-07-21 21:50:37
【问题描述】:

我正在尝试为一些本地 DLL 创建 C++/CLI 包装器。 这些 DLL 中有 7 个,将来还会更多,所以我需要动态加载它们。它们都具有相同的功能集。 LoadLibrary 和 GetProcAddress 在本机应用程序中可以很好地加载这些函数。

每当我加载 DLL 并调用 Initialize 时,都会收到 AccessViolationException。 我正在使用选择了 x86 平台的 C# 控制台应用程序进行测试。

更新: 不知道为什么我被否决了。这个问题在我的任何谷歌搜索中都没有得到回答。我已经搜索了半周才问。这里关于同一件事的所有问题都使用不同的方法。 MSDN 说本机互操作中的 AccessViolations 是严重编程错误的标志。我不明白我做错了什么。我正在编组我的字符串,并在调用之前检查 nullptrs。加载功能似乎有效。如果我输入了已知的错误函数名,或者我知道的 DLL 路径不正确,它会告诉我加载失败。如果我输入正确的路径/函数名称,它会说一切正常,但是当我尝试调用它时会崩溃。对于我正在测试的 DLL,函数 TSInit 实际上并没有在这个特定的 DLL 中做任何事情,但它可能会为具有相同接口的其他 DLL 做一些实际的工作。

更新 2:

我认为这个问题无法回答。正如我所说,有几个 DLL 具有完全相同的接口。现在,我发现其中一些有效,而另一些则无效。我用 dumpbin 检查了所有这些,以确认它们都是 x86 编译的,它们是。我不确定那些不起作用的 DLL 有什么问题。在原生 C++ 应用程序中,它们都按预期工作。

typedef long (WINAPI *TSRINIT)(long lType, HWND hParent, RECT *pRect);

namespace Imagery
{
    public ref class Recongizer
{
public:
    Recongizer(String^ DllPath) { LoadRecongizer(DllPath); }
    ~Recongizer() { UnloadLibrary(); }
    bool LoadRecongizer(String^ DllPath)
    {
        HInstance = ::LoadLibrary(msclr::interop::marshal_as<std::wstring>(DllPath).c_str());
        if (HInstance == nullptr) return false;
        if (!LoadFunctions())   return false;
        return true;
    }
    long Initalize(long lType)
    {
        if (HInstance == nullptr || TSInit == nullptr) return 0;
        return TSInit(0, nullptr, nullptr);
    }
private:
    void UnloadLibrary()
    {
        if (HInstance != nullptr) ::FreeLibrary(HInstance);
    }
    bool LoadFunctions()
    { 
        TSInit = (TSRINIT)::GetProcAddress(HInstance, "TSRInit");
        if (TSInit == nullptr)
        {
            ErrorMessage = "TSRInit could not be loaded.";
            return false;
        }
        return true;
    }
    property String^ ErrorMessage;
private:
    HINSTANCE HInstance{ nullptr };
    TSRINIT TSInit{ nullptr };
};

}

【问题讨论】:

  • 您无法对如此模糊的问题进行诊断。从 not 开始使用 LoadLibrary(),这完全没有意义。只需链接这些 DLL 的导入库并#include 相关的 .h 文件。三种更少的故障模式。
  • 访问冲突不是魔术。例如,您有一个堆栈跟踪。

标签: .net dll c++-cli interop mixed-mode


【解决方案1】:

调用约定可能有问题。确保所有 DLL 都使用相同的调用约定(即 WINAPI,根据您对 TSRINIT 的定义),否则您可能会遇到堆栈损坏,因为您的代码和 DLL 的代码可能需要不同的清理行为。有关概述,请参阅https://msdn.microsoft.com/en-us/library/984x0h58.aspx。不过,不确定为什么原生 C++ 应用程序可以工作 - 只是一个疯狂的猜测。

【讨论】:

    猜你喜欢
    • 2021-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-06
    • 1970-01-01
    • 1970-01-01
    • 2010-10-27
    • 2017-11-05
    相关资源
    最近更新 更多