How to pass function pointer from C# to a C++ Dll?(如何将函数指针从 C# 传递给 C++ Dll?)
问题描述
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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何将函数指针从 C# 传递给 C++ Dll?
- Web Api 中的 Swagger .netcore 3.1,使用 swagger UI 设置日期时间格式 2022-01-01
- 带有服务/守护程序应用程序的 Microsoft Graph CSharp SDK 和 OneDrive for Business - 配额方面返回 null 2022-01-01
- MoreLinq maxBy vs LINQ max + where 2022-01-01
- 如何用自己压缩一个 IEnumerable 2022-01-01
- C# 中多线程网络服务器的模式 2022-01-01
- 输入按键事件处理程序 2022-01-01
- WebMatrix WebSecurity PasswordSalt 2022-01-01
- 良好实践:如何重用 .csproj 和 .sln 文件来为 CI 创建 2022-01-01
- 在哪里可以找到使用中的C#/XML文档注释的好例子? 2022-01-01
- C#MongoDB使用Builders查找派生对象 2022-09-04