我目前正在研究与互操作相关的问题,并编写了一个小测试程序以帮助我弄清楚发生了什么(所讨论的问题涉及对更复杂的 native 函数的调用,因此很难发布在这里)。
无论如何,我有一个非常简单的 native dll,它只包含以下代码:
extern "C" __declspec(dllexport) void Foo( int* arr, int size );
void Foo( int* arr, int size )
{
for( int i = 0; i < size; ++i )
{
*arr++ = i;
}
}
我像这样从 C# 调用这个函数:
[DllImport("Interop.dll")]
public static extern void Foo( int[] arr, int size );
static void Main(...)
{
Test();
}
private static void Test()
{
int[] arr = new int[100];
Foo( arr, arr.Length );
}
执行“测试”后,我收到以下错误:
PInvokeStackImblanace was Detected
A call to PInvoke function 'WindowsFormsApplication2!WindowsFormsApplication2.Form1::Foo' 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.
所以,我不是互操作专家,但我看不出这段代码有什么问题。 native 签名需要一个指向 int 的指针,我正在传递对 int[]
的引用。就是说,它不起作用,所以我一定是错了。提前致谢。
编辑:好的,我将测试更改为尽可能简单:
extern "C" __declspec(dllexport) void Foo( int i );
void Foo( int i ) { }
C#:
[DllImport("Interop.dll")]
public static extern void Foo( int i );
private void Test()
{
Foo( 1 );
}
导致相同的错误。我是否错过了一些关于互操作中使用的调用约定的完整类(class)?这是怎么回事?
最佳答案
您需要指定一个正确的 calling convention . C/C++ 程序的默认调用约定是 cdecl , 但通过 PInvoke 导入时的默认调用约定是 StdCall .因此,您要么需要在导入时指定 Cdecl
约定,要么在导出时指定 __stdcall
。例如:
[DllImport("Interop.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Foo( int i );
private void Test()
{
Foo( 1 );
}
关于c# - 简单互操作测试;通过简单调用堆栈不平衡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5070752/