【发布时间】:2019-06-24 07:09:14
【问题描述】:
我有以下 C++ 代码,可编译为 dll:
typedef struct _RGB {
unsigned char R, G, B;
} RGB;
extern "C" __declspec(dllexport) RGB __stdcall TestMethod1() {
RGB rgb{1,2,3};
return rgb;
}
并在 C# 中使用:
static void Main(string[] args)
{
var res = TestMethod1();
}
[DllImport(@"D:\Develop\res\VSProjects\ConsoleApp1\Debug\Dll1.dll", CallingConvention = CallingConvention.StdCall)]
static extern RGB TestMethod1();
[StructLayout(LayoutKind.Sequential)]
struct RGB { public byte R, G, B; }
当以 x86 运行时,将 dll 构建为 x86 后,我收到错误 Attempted to read or write protected memory.。在 x64 中它工作正常。
当我使用托管/本机调试器时,我看到它在 return rgb; 上崩溃。
将返回类型更改为long(C# 中为int)时,即使在 x86 上也能正常工作。
RGB 结构 is blittable 那么为什么我会遇到这个问题?
【问题讨论】:
-
您应该添加
Pack参数。[StructLayout(LayoutKind.Sequential, Pack = 1)]到 StructLayout,因为你的结构是 3 个字节长。对于 c++ 你应该检查#pragma pack(push, 1) -
@JeroenvanLangen 不,这根本不会有任何区别,因为该结构包含 3 个字节并且所有可能的对齐方式都是相同的。实际上是错误的,因为 C++ 结构没有打包。
-
@DavidHeffernan 我不相信这是重复的,因为另一个问题是返回一个指针,这显然是行不通的。我正在返回结构本身,该问题中没有任何内容可以解释为什么它不起作用。
-
很好。我阅读了该问题中的 C# 代码,该代码假定结构是按值返回的。无论如何,你现在知道解决方案了。
-
如果你想了解它,你需要发现二进制接口的两侧是如何操作的。这可以通过例如在 CPU/asm 级别调试函数调用来完成。