Dmi*_*try 6 c++ pinvoke interop c++-cli marshalling
我正在使用本机DLL.我不确定,但我认为我不能使用PInvoke decl,因为它不会导出任何函数而且没有清单.DLL随附一个头文件,解释了如何使用它.头文件定义了无数的结构,枚举和一个使用工厂方法构造的类,该方法通过Windows函数访问::GetProcAddress(安全性通过默认).这个类包含我想在托管代码中使用的函数.
我已经成功地将类包装在CLI ref类中,并且可以在其上调用简单的方法,也包含它们.
我正在经历将一些结构从头文件转换为托管结构的过程.例如,Native结构:
struct FooACL{
int action;
unsigned long from,to;
char comment[64];
int reserved[17];
};
Run Code Online (Sandbox Code Playgroud)
变成托管结构:
[StructLayout(LayoutKind::Sequential, CharSet = CharSet::Ansi)]
public value struct ManagedFooACL{
int action;
int from,to;
[MarshalAs(UnmanagedType::ByValTStr, SizeConst = 64)]
String^ comment;
[MarshalAs(UnmanagedType::ByValArray, SizeConst = 17)]
array<int>^ reserved;
};
Run Code Online (Sandbox Code Playgroud)
据我所知,这应该使托管结构blittable?以及遵循类似模式或嵌套结构级别的任何其他结构.只要指定了布局并且没有任何blittable用MarshalAs装饰,整个结构是否会闪烁?
所以,我试图看看是否有使用Marshal::Copy或Marshal::PtrToStructure转换FooACL*数组的方法array<ManagedFooACL>^.
我从函数调用中获取FooACL*数组; 我自己不分配.
int total;
FooACL* foos = unamagedClass->GetFooACLS(&total);
Run Code Online (Sandbox Code Playgroud)
total 是一个输入/输出,它获取返回的数组的大小.
到目前为止我设法做了什么,有什么工作:
ManagedFooACL first = static_cast<ManagedFooACL>(Marshal::PtrToStructure(IntPtr(&foos [0]), ManagedFooACL::typeid));
Run Code Online (Sandbox Code Playgroud)
我无法理解的是为什么这不是:
array<ManagedFooACL>^ mfoos = gcnew array<ManagedFooACL>(total);
Marshal::PtrToStructure(IntPtr(&foos), mfoos);
Run Code Online (Sandbox Code Playgroud)
这引发了一个:
System.ArgumentException was unhandled
Message=The specified structure must be blittable or have layout information.
Parameter name: structure
Source=mscorlib
ParamName=structure
Run Code Online (Sandbox Code Playgroud)
有没有办法在一次调用中复制数组数据,还是我真的需要进行for循环?所有这些编组功能似乎都很愚蠢.
做了更多研究后,答案似乎是否定的。不可能在不循环的情况下自动编组 an arrayof structs。
struct我认为编组工作的主要原因PtrToStructure是因为结构是静态/预定义的。编译器知道如何布局内存。由于您获得了动态大小,array因此无法提前指定内存布局。所以你必须循环动态数量的structs。
或者,如果您知道您将始终获得一个 X 长度的数组,您可以定义自己的托管持有一个元素,即带有 a和值 X 的struct数组,然后将本机强制转换为.ManagedFooACLByValArraySizeConstarraystruct