原生函数的包装器

时间:2016-04-01 23:23:47

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

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

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

更新 不知道为什么我投了票。我的任何谷歌搜索都没有回答这个问题。我甚至在询问之前已经搜索了半个星期。这里关于同一件事的所有问题都使用不同的方法。 MSDN表示,本机互操作中的AccessViolations是严重编程错误的标志。我不明白我做错了什么。我正在编组我的字符串,并在调用之前检查nullptrs。加载功能似乎有效。如果我输入已知的错误函数名称,或者我知道的DLL路径不正确,它会告诉我加载失败。如果我输入正确的路径/功能名称,它表示一切正常,但在我尝试调用它时会崩溃。函数TSInit,对于我正在测试的DLL实际上并没有在这个特定的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 };
};

}

1 个答案:

答案 0 :(得分:0)

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