我正在编写一个C ++ / CLI层来处理一些互操作。
本机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;
}
这样做会出错:
错误2错误C3821:'void Test :: GetFoo(HANDLE)':托管类型或函数不能在非托管函数中使用
如果本机结构和gcnew
不能存在于同一个函数中,那么人们怎么能希望(甚至手动)在两者之间编组数据呢?
这里有许多Q / A涉及包装非托管类,这似乎与此无关。
答案 0 :(得分:11)
托管代码中不支持对齐的数据类型
这是真正的错误消息,遗憾的是它没有显示在错误列表窗口中。您只能在“输出”窗口中看到它。编译器错误消息看起来很奇怪时要记住的事情。
是的,它是准确的,托管代码不会运行堆栈对齐保证,以使这个结构对齐。 32位代码运行,对齐为4,64位代码可以提供8.不够好得到16.编译器也无法做到这一点,通常的堆栈指针操作在IL中不可用,这搞砸了抖动生成的元数据,告诉垃圾收集器当它走过堆栈时对象的引用位置。
所以,没有办法,你不能把它变成局部变量。您已经有了选择,最直接的方式是分配它:
#include <malloc.h>
....
FOO* value = (FOO*)_aligned_malloc(sizeof(FOO), __alignof(FOO));
try {
// etc...
}
finally {
_aligned_free(value);
}