【问题标题】:Calling a DLL function that contains a function pointer from C#从 C# 调用包含函数指针的 DLL 函数
【发布时间】:2012-10-28 03:14:15
【问题描述】:

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

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

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

// 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 ; 
    }
}

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

'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).

我不确定下一步该做什么。

我的问题是:

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

【问题讨论】:

标签: c# c++ dll function-pointers


【解决方案1】:

这是因为默认情况下,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 );
    // ...
}

【讨论】:

  • [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 只有在 x86 (Win32 / WoW64) 模式下运行时才需要。在 64 位模式下,只有一个调用约定,该属性被忽略。如果您在 x64 机器上开发,您可能很容易忘记对 32 位的特殊处理。
  • @linquize 错误unbalanced the stack 只能由C++ 函数中堆栈变量中的underflow/overflow 引起(在C# 中你不能这样做)或错误的调用约定。所以调用者肯定不是在 X64 模式下运行代码!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多