是否可以使用for循环将本机struct数组封送到托管数组

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::CopyMarshal::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循环?所有这些编组功能似乎都很愚蠢.

Dmi*_*try 3

做了更多研究后,答案似乎是否定的。不可能在不循环的情况下自动编组 an arrayof structs。

struct我认为编组工作的主要原因PtrToStructure是因为结构是静态/预定义的。编译器知道如何布局内存。由于您获得了动态大小,array因此无法提前指定内存布局。所以你必须循环动态数量的structs。

或者,如果您知道您将始终获得一个 X 长度的数组,您可以定义自己的托管持有一个元素,即带有 a和值 X 的struct数组,然后将本机强制转换为.ManagedFooACLByValArraySizeConstarraystruct