如何将函数指针从 C# 传递给 C++ Dll?

How to pass function pointer from C# to a C++ Dll?(如何将函数指针从 C# 传递给 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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)