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

时间:2012-12-27 23:17:54

标签: c++ interop c++-cli pinvoke marshalling

我正在使用本机DLL。我不确定,但我认为我不能使用PInvoke decl,因为它不会导出任何函数而且没有清单。 DLL随附一个头文件,解释了如何使用它。头文件定义了无数的结构,枚举和一个使用工厂方法构造的类,该方法通过Windows函数::GetProcAddress访问(安全性通过默认)。 这个类包含我想在托管代码中使用的函数。

我已成功将该类包装在CLI ref类中,并且可以在其上调用简单的方法,同时包装它们。

我正在经历将一些结构从头文件转换为托管结构的过程。例如,Native结构:

struct FooACL{
    int               action;                
    unsigned long     from,to;               
    char              comment[64]; 
    int               reserved[17];          
};

变成托管结构:

[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;
};

据我所知,这应该使托管结构变得blittable?以及遵循类似模式或嵌套结构级别的任何其他结构。只要指定了布局并且没有任何blittable用MarshalAs装饰,整个结构是否会闪烁?

因此,我正在尝试查看是否有办法使用Marshal::CopyMarshal::PtrToStructureFooACL*数组转换为array<ManagedFooACL>^

我从函数调用中获取FooACL *数组;我自己不分配它。

int total;
FooACL* foos = unamagedClass->GetFooACLS(&total);

total是一个输入/输出,它获取返回的数组的大小。

到目前为止我设法完成的工作是什么:

ManagedFooACL first = static_cast<ManagedFooACL>(Marshal::PtrToStructure(IntPtr(&foos [0]), ManagedFooACL::typeid));

我无法理解的是为什么不这样做:

array<ManagedFooACL>^ mfoos = gcnew array<ManagedFooACL>(total);
Marshal::PtrToStructure(IntPtr(&foos), mfoos);

这引发了一个:

System.ArgumentException was unhandled
  Message=The specified structure must be blittable or have layout information.
Parameter name: structure
  Source=mscorlib
  ParamName=structure

有没有办法在一次调用中复制数组数据,还是我真的需要进行for循环?所有这些编组功能似乎都很愚蠢。

1 个答案:

答案 0 :(得分:2)

做了更多研究之后,答案似乎是否定的。如果没有循环,则无法自动封送array struct个。

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

或者,如果您知道自己将始终获得X长度数组,则可以定义自己的托管struct,其中包含一个元素,即ManagedFooACL的数组{{1} }和ByValArray X的值,只需将原始SizeConst投射到array