【问题标题】:P/Inovke parameters offset by 32 bits when compiled in 64 bitP/Inovke 参数在 64 位编译时偏移 32 位
【发布时间】:2013-09-29 19:52:18
【问题描述】:

关注PInvoke byte array to char not behaving properly in 64 bit。 (陈旧的问题和我的怀疑是错误的,因此标题和描述不合适)。

我正在使用 P/Invoke 从 C# 调用 C++ 代码。我在 VS 的构建配置中将 C# 和 C++ 项目设置为在 x64 中构建。当我运行这个程序时,P/Invoke 调用的参数被移动了 32 位,如下所示

C# : |Parameter 1|Parameter 2|Parameter 3|Parameter 4|
           |           |           |           |           |
           V           V           V           V           V
C++:             |Parameter 1|Parameter 2|Parameter 3|Parameter 4|

所以如果我从 C# 端传递 1,2,3,4,C++ 端会收到 2,3,4,garbage。

我通过在 C# 参数前面传入一个额外的 int 而不更改 C++ 端来解决这个问题。这会将参数偏移 32 位并重新对齐它们,程序可以完美运行。

有谁知道导致这种奇怪偏移的原因以及纠正它的正确方法吗?

这是一个显示我的方法签名的简化示例

C#端:

[DllImport(@"C:\FullPath\CppCode.dll", EntryPoint = "MethodName",
CallingConvention = CallingConvention.Cdecl))]
private static extern bool MethodName(parameters);

C++ 方面:

extern "C" __declspec(dllexport)
bool CppClass::MethodName(parameters)

我怀疑由于参数偏离了 32 位,因此可能有些事情并没有真正在 64 位中正确完成。也许在调用方法时,在变量之前传递了一个隐式指针?如果这只是 C# 端的一个 32 位指针,而 C++ 期望一个 64 位指针,那可能会导致这种偏移情况,但我不确定。

【问题讨论】:

  • 您不应显示简化版本。魔鬼在于细节:-)。另外,MethodName 不应该是 C++ 类实例方法,而是类 C 函数。
  • 那么应该是静态方法吗?还是我应该把它从课堂上分离出来?
  • static 我猜应该可以工作,这是因为当有人调用该方法时,第一个参数是指向类实例的指针,所以你需要摆脱它。
  • 使其成为静态工作。谢谢西蒙!如果您想重新发布您的评论作为答案,我会接受。
  • 我相信我在最后一个问题上告诉了你这一切!

标签: pointers 64-bit pinvoke 32bit-64bit


【解决方案1】:

MethodName 不应是类实例方法,因为第一个字节(x86 世界中为 4,x64 世界中为 8)将用于非托管世界中的类实例指针。

所以,它应该是一个静态方法(或 C 风格的方法)。

【讨论】:

    猜你喜欢
    • 2011-04-12
    • 1970-01-01
    • 2017-01-21
    • 2018-08-04
    • 1970-01-01
    • 2017-03-11
    • 2013-08-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多