我正在编写一个 C++/CLI 层来处理一些互操作。
native API 填充涉及固定数组、联合、匿名结构等的复杂结构:
typedef struct DECLSPEC_ALIGN(16) _FOO {
union {
BAR Bar;
struct {
POP Array[8];
DWORD More;
};
};
} FOO, *PFOO;
我正在尝试将此数据结构转换为更“合理”的 .NET 类,以供 C# 使用。问题是,我不能在同一个函数中使用这个遗留结构和 gcnew
我的新类:
Foo^ Test::GetFoo(HANDLE h)
{
FOO foo; // Necessarily unmanaged
if (!::GetFoo(h, &foo))
throw gcnew Exception("GetFoo failed");
Foo^ result = gcnew Foo(); // Necessarily managed
// populate result
return result;
}
这样做会产生错误:
Error 2 error C3821: 'void Test::GetFoo(HANDLE)': managed type or function cannot be used in an unmanaged function
如果 native 结构和 gcnew
不能存在于同一个函数中,那么人们怎么可能希望(甚至手动)在两者之间编码数据?
这里的许多问答涉及包装非托管类,这在这里似乎无关紧要。
最佳答案
Aligned data types not supported in managed code
这才是真正的错误信息,不幸的是它没有出现在错误列表窗口中。您只能在“输出”窗口中看到它。当编译器错误消息看起来很奇怪时要记住一些事情。
是的,它是准确的,托管代码不会在堆栈对齐保证的情况下运行,而堆栈对齐保证是对齐此结构所需的。 32 位代码以 4 对齐运行,64 位代码可以提供 8。不足以获得 16。编译器对此也无能为力,通常的堆栈指针操作在 IL 中不可用,这搞砸了抖动生成的元数据告诉垃圾收集器在遍历堆栈时在哪里查找对象引用。
所以,没办法,你不能让它成为局部变量。您有多种选择,最直接的方法是分配它:
#include <malloc.h>
....
FOO* value = (FOO*)_aligned_malloc(sizeof(FOO), __alignof(FOO));
try {
// etc...
}
finally {
_aligned_free(value);
}
关于.net - 解决错误 C3821 : managed type or function cannot be used in an unmanaged function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24355263/