调用包含函数指针的DLL函数从C# [英] Calling a DLL function that contains a function pointer from C#

查看:526
本文介绍了调用包含函数指针的DLL函数从C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用C ++编写的DLL,它包含导出的函数,该函数具有一个用作回调函数的函数指针。

  // C ++ 
DllExport unsigned int DllFunctionPointer(unsigned int i,unsigned int(* TimesThree) )){
return TimesThree(i);
}



我有一个CSharp应用程序,我想用来调用DLL函数。

  // C#
public unsafe委托System.UInt32 CallBack(System.UInt32 number);
类程序
{
[DllImport(SimpleDLL.dll)]
public static extern System.UInt32 DllFunctionPointer(System.UInt32 i,CallBack cb);

static unsafe void Main(string [] args)
{
System.UInt32 j = 3;
System.UInt32 jRet = DllFunctionPointer(j,CallBack);
System.Console.WriteLine(j = {0},jRet = {1},j,jRet);
}

static System.UInt32 CallBack(System.UInt32 number){
return number * 3;
}
}

上述代码的问题是应用程序崩溃并显示以下错误消息。

 'CallingACallbackFromADLL.vshost.exe'(Managed(v4.0.30319)):加载'C:\XXXX\CallingACallbackFromADLL .exe',加载符号。 
托管调试助手'PInvokeStackImbalance'已在C:\XXXX\CallingACallbackFromADLL.vshost.exe中检测到问题。
附加信息:调用PInvoke函数CallingACallbackFromADLL!CallingACallbackFromADLL.Program :: DllFunction使堆栈不平衡。这很可能是因为托管PInvoke签名与非托管目标签名不匹配。检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。

程序'[9136] CallingACallbackFromADLL.vshost.exe:Managed(v4.0.30319)'已退出,代码为1073741855(0x4000001f)。

我不知道接下来该做什么。



我的问题是:




  • 调用C ++的正确方法是什么DLL函数,它包含来自C#应用程序的回调指针。

    这是因为默认情况下调用 C#中的函数约定 是 __ stdcall 但在 C / C ++ 默认为 __ cdecl ,所以你应该改变你的函数的调用约定如下:

      [UnmanagedFunctionPointer(CallingConvention.Cdecl) ] 
    public delegate void TimesTree(uint frame);
    [DllImport(SimpleDLL.dll)]
    public static extern System.UInt32 DllFunctionPointer(uint i,
    [MarshalAs(UnmanagedType.FunctionPtr)] TimesTree callback);

    static unsafe void Main(string [] args)
    {
    // ...
    System.UInt32 jRet = DllFunctionPointer(j,CallBack);
    // ...
    }


    I have a DLL that is written in C++ that includes exported function that has a function pointers to be used as callback function.

    // C++ 
    DllExport unsigned int DllFunctionPointer( unsigned int i, unsigned int (*TimesThree)( unsigned int number ) ) {
        return TimesThree( i )  ; 
    }
    

    I have a CSharp application that I would like to use to invoke the DLL functions.

    // C#
    public unsafe delegate System.UInt32 CallBack( System.UInt32 number ); 
    class Program
    {
        [DllImport("SimpleDLL.dll")]
        public static extern System.UInt32 DllFunctionPointer( System.UInt32 i, CallBack cb) ;
    
        static unsafe void Main(string[] args)
        {
            System.UInt32 j = 3;
            System.UInt32 jRet = DllFunctionPointer(j, CallBack );
            System.Console.WriteLine("j={0}, jRet={1}", j, jRet); 
        }
    
        static System.UInt32 CallBack( System.UInt32 number ) {
            return number * 3 ; 
        }
    }
    

    The problem with the above code is that the application crashes with the following error message.

    'CallingACallbackFromADLL.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\XXXX\CallingACallbackFromADLL.exe', Symbols loaded.
    Managed Debugging Assistant 'PInvokeStackImbalance' has detected a problem in 'C:\XXXX\CallingACallbackFromADLL.vshost.exe'.
    Additional Information: A call to PInvoke function 'CallingACallbackFromADLL!CallingACallbackFromADLL.Program::DllFunction' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
    
    The program '[9136] CallingACallbackFromADLL.vshost.exe: Managed (v4.0.30319)' has exited with code 1073741855 (0x4000001f).
    

    I am not sure what to do next.

    My question is:

    • What is the correct way to call a C++ DLL function that contains a Callback pointer from a C# application.

    解决方案

    This is because by default calling convention of functions in C# is __stdcall but in C/C++ default is __cdecl, so you should change calling convention of your function as follow:

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void TimesTree( uint frame );
    [DllImport("SimpleDLL.dll")]
    public static extern System.UInt32 DllFunctionPointer( uint i,
        [MarshalAs(UnmanagedType.FunctionPtr)] TimesTree callback ) ;
    
    static unsafe void Main(string[] args)
    {
        // ...
        System.UInt32 jRet = DllFunctionPointer(j, CallBack );
        // ...
    }
    

    这篇关于调用包含函数指针的DLL函数从C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆