从 C# 调用 DLL 时,为什么小结构会导致函数参数不一致?
我正在编写 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
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.