【问题标题】:Simple Interop Test; Stack Unbalanced by a simple call简单互操作测试;通过一个简单的调用实现堆栈不平衡
【发布时间】:2011-02-22 05:06:06
【问题描述】:

我目前正在研究一个与互操作相关的问题,并编写了一个小型测试程序来帮助我弄清楚发生了什么(有问题的问题涉及对更复杂的本机函数的调用,并且很难发布在这里)。

无论如何,我有一个非常简单的原生 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

对 PInvoke 函数“WindowsFormsApplication2!WindowsFormsApplication2.Form1::Foo”的调用使堆栈失衡。这可能是因为托管 PInvoke 签名与非托管目标签名不匹配。检查 PInvoke 签名的调用约定和参数是否与目标非托管签名匹配。

所以,我不是互操作专家,但我看不出这段代码有什么问题。本机签名需要一个指向 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 );
}

导致相同的错误。我是否错过了一些关于互操作中使用的调用约定的完整课程?这是怎么回事?

【问题讨论】:

    标签: c# interop


    【解决方案1】:

    您需要指定正确的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 );
    }
    

    【讨论】:

    • 谢谢,就是这样。我过去调用的库必须设置为开箱即用地使用 StdCall,这就是为什么我从来没有遇到过问题。再次感谢。
    猜你喜欢
    • 2016-04-22
    • 2018-05-15
    • 1970-01-01
    • 1970-01-01
    • 2019-07-11
    • 1970-01-01
    • 2022-07-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多