【问题标题】:When calling DLLs from C#, why would small structs misalign function parameters?从 C# 调用 DLL 时,为什么小型结构会错位函数参数?
【发布时间】:2011-07-19 23:53:25
【问题描述】:

我正在编写一个 c#/c++ 应用程序,当我尝试传递一个仅包含两个浮点数的结构时遇到了问题。例如:

[DllImport("Resources\\CppInterface", EntryPoint = "?ReadDllTest@ScriptParserInterface@@YA?AVDllTest@@PAVScriptParser@@PB_W@Z", CharSet = CharSet.Unicode)]
private static extern DllTest ReadDllTestS(IntPtr scriptParser, string name);

当 DLLTest 包含 3 或 4 个浮点数时工作得很好。但是,当它包含 2 时,intptr 和传递的字符串指针在 C++ 端会出现 1 个字节未对齐。

知道是什么原因造成的吗?

示例结构布局:

[StructLayout( LayoutKind.Sequential )]
public struct DllTest
{
    public float a, b;/*, c, d; (works if c or/d are in)*/

    DllTest( float i, float j )
    {
        a = i;
        b = j;
    }
}

C++ 方面:

DllTest ScriptParserInterface::ReadDllTest( ScriptParser* scriptParser, const wchar_t* name )
{
     return DllTest(); /* If only using two variables in DLLTest. scriptParser and name no longer work, but are located at *((&scriptParser)-1) and *((&name)-1)
}

任何建议将不胜感激。谢谢。

【问题讨论】:

    标签: c# c++ string marshalling


    【解决方案1】:

    ScriptParserInterface 必须是命名空间名称,如果它是类名,您将永远无法使用它。根据损坏的名称,函数是 __cdecl,您忘记在 [DllImport] 声明中使用 CallingConvention 属性。您应该收到 PInvokeStackImbalance MDA 警告。既然你没有,我不得不假设你将它作为 64 位代码运行。

    忘记 CallingConvention 本身就足以摆脱堆栈。从那里开始。

    【讨论】:

    • 嘿,非常感谢您的帮助。我尝试添加额外的行,但这并没有真正起到任何作用。我一直在阅读不同的模式,Windows 上的默认值似乎是 stdcall,但将它们更改为 cdecl 并没有帮助。
    • 我将上面的代码修改为... CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl )]。哦,你说它是 c++ 端的命名空间是完全正确的,但它都是 32 位的,而不是 64 位。我还应该补充一点,在 c++ 端,函数声明为:_declspec( dllexport ) DllTest ReadDllTest( ScriptParser* scriptParser, const wchar_t* name );
    猜你喜欢
    • 2022-11-11
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 2010-10-15
    • 2021-08-19
    • 1970-01-01
    相关资源
    最近更新 更多