我正在使用本机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::Copy
或Marshal::PtrToStructure
将FooACL*
数组转换为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循环?所有这些编组功能似乎都很愚蠢。
答案 0 :(得分:2)
做了更多研究之后,答案似乎是否定的。如果没有循环,则无法自动封送array
struct
个。
我认为struct
编组与PtrToStructure
一起使用的主要原因是因为结构是静态的/预定义的。编译器知道如何布局内存。因为,您获得了动态大小array
,所以无法提前指定内存布局。因此,您必须循环动态数struct
s。
或者,如果您知道自己将始终获得X长度数组,则可以定义自己的托管struct
,其中包含一个元素,即ManagedFooACL
的数组{{1} }和ByValArray
X的值,只需将原始SizeConst
投射到array
。