从 C# 调用 DLL 时,为什么小结构会导致函数参数不一致?

发布于 2024-10-25 18:32:11 字数 1002 浏览 5 评论 0原文

我正在编写 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)
}

非常感谢任何建议。谢谢。

I'm writing a c# / c++ application I've ran into problems when I tried passing a structure containing only two floats across. For example:

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

Works perfectly fine when DLLTest contains 3 or 4 floats. However, when it contains 2, the intptr and the string pointer passed through ends up 1 byte misaligned on the C++ side.

Any idea what could cause this?

Example struct layout:

[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++ side:

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)
}

Any suggestions would be very much appreciated. Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

归属感 2024-11-01 18:32:11

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

忘记 CallingConvention 本身就足以导致堆栈溢出。从那里开始。

ScriptParserInterface must be a namespace name, you'd never make it work if it is a class name. The function is __cdecl according to the mangled name, you forgot to use the CallingConvention property in your [DllImport] declaration. You should have gotten a PInvokeStackImbalance MDA warning. Since you didn't, I have to assume you run this as 64-bit code.

Forgetting CallingConvention in itself could be enough to throw off the stack. Start there.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文