【发布时间】: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