有没有可能在没有for循环的情况下将本机结构数组封送到托管数组?

Is it possible to marshal native struct array to managed array with out a for loop

本文关键字:数组 结构 有可能 for 循环 情况下 本机      更新时间:2023-10-16

我使用的是本地DLL。我不确定,但我想我不能使用PInvoke decl's,因为它不导出任何函数,也没有清单。DLL提供了一个头文件,解释了如何使用它。头文件定义了无数的结构体,枚举和一个类,使用工厂方法来构造,通过Windows函数::GetProcAddress(通过晦涩实现安全)来访问。这个类包含我想在托管代码中使用的函数。

我已经成功地将类包装在CLI ref类中,并且可以在其上调用简单的方法,也可以包装这些方法。

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

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

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

因此,我试图看看是否有方法使用Marshal::CopyMarshal::PtrToStructureFooACL*数组转换为array<ManagedFooACL>^

我得到的FooACL*数组从一个函数调用;我自己不分配。

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

total是一个获取返回数组大小的in/out操作。

到目前为止我做了什么,工作是什么:

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循环?这些封送功能看起来有点傻。

在做了更多的研究之后,答案似乎是否定的。在不循环的情况下自动封送array/struct是不可能的。

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

或者,如果你知道你将总是得到一个长度为X的数组,你可以定义你自己的托管struct来保存一个元素,即ManagedFooACL的数组,ByValArraySizeConst的值为X,并将本地array转换为struct