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