C#在调用前检查非托管函数指针是否安全 我在C++中使用了一个单独的代码,使用 LoadLibrary < />代码> GePosiald> < /C> >和 FreeLibrary >代码>手动链接从非托管C++ DLL导出的多个函数。大多数对象的声明如下所示: [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate int Function_prototype(int someParams); Function_prototype MyFunction; public myFunction(int someParams) { return MyFunction(someParams); } //repeated many times with minor variations for each function IntPtr dllHandle = LoadLibrary(@"C:\path\to\file.dll"); IntPtr addressToFunction = GetProcAddress(dllHandle, "MyFunction"); //error checking omitted to keep example brief MyFunction = (MyFunction_Prototype)Marshal.GetDelegateForFunctionPointer(addressToFunction, typeof(MyFunction)) public myFunction(int someParams) { try { return MyFunction(someParams); } catch(AccessViolationException) { throw new UsefulErrorException(); } }
并使用如下方式分配代理:C#在调用前检查非托管函数指针是否安全 我在C++中使用了一个单独的代码,使用 LoadLibrary < />代码> GePosiald> < /C> >和 FreeLibrary >代码>手动链接从非托管C++ DLL导出的多个函数。大多数对象的声明如下所示: [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate int Function_prototype(int someParams); Function_prototype MyFunction; public myFunction(int someParams) { return MyFunction(someParams); } //repeated many times with minor variations for each function IntPtr dllHandle = LoadLibrary(@"C:\path\to\file.dll"); IntPtr addressToFunction = GetProcAddress(dllHandle, "MyFunction"); //error checking omitted to keep example brief MyFunction = (MyFunction_Prototype)Marshal.GetDelegateForFunctionPointer(addressToFunction, typeof(MyFunction)) public myFunction(int someParams) { try { return MyFunction(someParams); } catch(AccessViolationException) { throw new UsefulErrorException(); } },c#,delegates,unmanaged,C#,Delegates,Unmanaged,并使用如下方式分配代理: [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate int Function_prototype(int someParams); Function_prototype MyFunction; public myFunction(int someParams) { return MyFunction(someParams); } //repeated many times with minor
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int Function_prototype(int someParams);
Function_prototype MyFunction;
public myFunction(int someParams)
{
return MyFunction(someParams);
}
//repeated many times with minor variations for each function
IntPtr dllHandle = LoadLibrary(@"C:\path\to\file.dll");
IntPtr addressToFunction = GetProcAddress(dllHandle, "MyFunction");
//error checking omitted to keep example brief
MyFunction = (MyFunction_Prototype)Marshal.GetDelegateForFunctionPointer(addressToFunction, typeof(MyFunction))
public myFunction(int someParams)
{
try
{
return MyFunction(someParams);
}
catch(AccessViolationException)
{
throw new UsefulErrorException();
}
}
(注意:我在下一段中提到了访问冲突异常。它们与上述步骤无关,它似乎工作正常,并且在访问冲突发生之前,委托将对函数的多次调用有效)
我们正在尝试诊断一些偶尔出现的访问冲突异常,这些异常在调用其中一个函数时会意外出现。因此,我正在探索解决方案,以便在问题导致整个系统崩溃之前确定问题我看到两种方法,我需要帮助找出如何实现其中一种,如果两者都可行,请列出每种方法的优缺点。
1) 在调用函数之前,是否有方法检查委托是否不再有效?我可以修改上面的myFunction
的定义,使其更像这样:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int Function_prototype(int someParams);
Function_prototype MyFunction;
public myFunction(int someParams)
{
return MyFunction(someParams);
}
//repeated many times with minor variations for each function
IntPtr dllHandle = LoadLibrary(@"C:\path\to\file.dll");
IntPtr addressToFunction = GetProcAddress(dllHandle, "MyFunction");
//error checking omitted to keep example brief
MyFunction = (MyFunction_Prototype)Marshal.GetDelegateForFunctionPointer(addressToFunction, typeof(MyFunction))
public myFunction(int someParams)
{
try
{
return MyFunction(someParams);
}
catch(AccessViolationException)
{
throw new UsefulErrorException();
}
}
但是,添加到我要导入的每个函数中会很乏味。我查看了文档,在我尝试调用它之前,如果我能确定MyFunction
是无效的,这对我来说并不明显。我想要像这样的东西:
if(!MyFunction.IsValid())
throw new UsefulErrorException();
return MyFunction(someParams);
但写几十遍仍然很乏味。有没有一种简单的方法可以在它被调用之前判断它是否会失败
2) 如果我必须满足于(1)中详述的
try/catch
示例,那么有没有办法让它更通用,这样我就不必重写几十次try/catch了?它必须具有足够的通用性,以便我可以传入非托管委托、其参数(无params
,但它们包含许多不同数量和类型的参数)以及各种返回类型(void
,int
,IntPtr
,string
,bool
)。我觉得有一种通用的方法,否则会有违规的味道。这是不可能的,只要你尝试解决这个问题,它就不会再发生了。必须调用GCHandle.Alloc()以确保委托不能被垃圾收集。GC完全不知道本机代码正在使用它。请记住LoadLibrary+GetProcAddress有多痛苦,尽可能使用[DllImport]。这和我做的完全一样。@HansPassantDllImport
不是一个选项,因为我工作的人设置了约束,否则我会是。我用它来引入LoadLibrary
,GetProcAddress
,和freebrary
,但仅此而已。