问题描述
C++ dll中定义的函数是:
The function defined in C++ dll is:
static double (*Func1)(double);
EXTERN_C __declspec(dllexport) __stdcall double TestDelegate(double (*fun)(double))
{
Func1 = fun;
return Func1(25.0);
}
void My_Real_purpose()
{
SomeClass a;
a.SetFunction(Func1);//Define behaviour of a by C# in runtime
a.DoSomething();//Even I want it runs in another thread!
}
我尝试在 C# 中这样调用它:
And I tried to call it in C# like this:
class A
{
[DllImport("DllName.dll")]
public extern static double TestDelegate(IntPtr f);
public delegate double MyFuncDelegate(double x);
public static double MyFunc(double x)
{
return Math.Sqrt(x);
}
static MyFuncDelegate ff;
static GCHandle gch;
public static double Invoke()
{
ff = new MyFuncDelegate(MyFunc);
gch = GCHandle.Alloc(ff);
double c = TestDelegate(Marshal.GetFunctionPointerForDelegate(ff));//Error occurs this line
gch.Free();
return c;
}
}
编译没有错误.但是运行时VS2012显示Access Violation Exception"的错误.
It is compiled without error.But when it runs,VS2012 display an error of "Access Violation Exception".
我已经搜索并尝试了很多方法,例如传递委托而不是 IntPtr,但所有方法都失败了.
I have searched and tried a lot of ways,such as passing a delegate rather than a IntPtr,but all of them turned out to be failed.
那么,在包含函数指针的dll中使用API函数的正确方法是什么?或者如何实现My_Real_purpose"函数?
So,what is the correct way to use an API function in a dll which contains function pointer?Or how to realize "My_Real_purpose" function?
推荐答案
您的委托使用 cdecl
调用约定.因此,在 C# 中,您可以像这样声明委托:
Your delegate uses the cdecl
calling convention. In C# you would therefore declare the delegate like this:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate double CallbackDelegate(double x);
作为替代方案,您可以决定将 C++ 中的函数指针声明为 __stdcall
,在这种情况下,您将删除 UnmanagedFunctionPointer
属性并依赖默认调用约定是 CallingConvention.StdCall
.
As an alternative, you could decide to declare the function pointer in C++ as __stdcall
, in which case you would remove the UnmanagedFunctionPointer
attribute and rely on the default calling convention being CallingConvention.StdCall
.
这样实现:
public static double MyFunc(double x)
{
return Math.Sqrt(x);
}
为了使非托管函数指针保持活动状态(防止 GC),您需要在变量中保存委托的实例.
In order to keep the unmanaged function pointer alive (guarding against GC), you need to hold an instance of the delegate in a variable.
private static CallbackDelegate delegateInstance;
....
delegateInstance = MyFunc;
在您在这里的简单示例中,C++ 代码不使用 TestDelegate
之外的非托管函数指针,但在更复杂的示例中,您可以这样做,在这种情况下,您必须保留非托管函数指针活着.
In the simple example that you have here, the C++ code does not use the unmanaged function pointer outside of TestDelegate
, but in a more complex example you may do so, in which case you must keep the unmanaged function pointer alive.
你导入的函数是这样声明的:
The function that you import is declared like this:
[DllImport("DllName.dll")]
public extern static double TestDelegate(CallbackDelegate f);
你可以这样称呼它:
double retval = TestDelegate(delegateInstance);
这篇关于如何将函数指针从 C# 传递给 C++ Dll?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!