返回结构时,PInvoke 仅适用于 64 位
PInvoke only works in 64 bit, when returning a struct
我有以下 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 中它工作正常。
当我使用 managed/native 调试器时,我看到它在 return rgb;
上崩溃。
将 return 类型更改为 long
(C# 中的 int
)时,即使在 x86 下也能正常工作。
RGB
结构 is blittable 为什么我会遇到这个问题?
不要对 "complex" return 类型使用结构,更喜欢这样的东西:
C++:
extern "C" __declspec(dllexport) void __stdcall TestMethod2(RGB *prgb) {
prgb->R = 1;
prgb->G = 2;
prgb->B = 3;
}
C#:
[DllImport(@"D:\smo\source\repos\ConsoleApplication4\Debug\Dll1.dll")]
static extern void TestMethod2(ref RGB rgb);
static void Main(string[] args)
{
var rgb = new RGB();
TestMethod2(ref rgb);
}
请注意,在您的特定情况下,它会失败,因为结构大小为 3,因此如果您像这样更改结构,则可以使其正常工作,例如:
C++:
typedef struct _RGB {
unsigned char R, G, B, A;
} RGB;
C#
[StructLayout(LayoutKind.Sequential)]
struct RGB { public byte R, G, B, A; }
根据此定义,大小将为 4,因此 C++ 编译器将生成一个代码,该代码将 return 一个 int32 值而不是 returning - 可能 - 对某些内部存储器的引用当执行到达 .NET 端时,它将消失。这纯属运气(或 hack),我猜取决于 C++ 编译器。
我有以下 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 中它工作正常。
当我使用 managed/native 调试器时,我看到它在 return rgb;
上崩溃。
将 return 类型更改为 long
(C# 中的 int
)时,即使在 x86 下也能正常工作。
RGB
结构 is blittable 为什么我会遇到这个问题?
不要对 "complex" return 类型使用结构,更喜欢这样的东西:
C++:
extern "C" __declspec(dllexport) void __stdcall TestMethod2(RGB *prgb) {
prgb->R = 1;
prgb->G = 2;
prgb->B = 3;
}
C#:
[DllImport(@"D:\smo\source\repos\ConsoleApplication4\Debug\Dll1.dll")]
static extern void TestMethod2(ref RGB rgb);
static void Main(string[] args)
{
var rgb = new RGB();
TestMethod2(ref rgb);
}
请注意,在您的特定情况下,它会失败,因为结构大小为 3,因此如果您像这样更改结构,则可以使其正常工作,例如:
C++:
typedef struct _RGB {
unsigned char R, G, B, A;
} RGB;
C#
[StructLayout(LayoutKind.Sequential)]
struct RGB { public byte R, G, B, A; }
根据此定义,大小将为 4,因此 C++ 编译器将生成一个代码,该代码将 return 一个 int32 值而不是 returning - 可能 - 对某些内部存储器的引用当执行到达 .NET 端时,它将消失。这纯属运气(或 hack),我猜取决于 C++ 编译器。