Is it possible to marshal your own array of structures into a managed array without a for loop

I am using a native DLL. I am not sure, but I think that I can not use PInvoke decl with it, since it does not export any functions and does not have a manifest. The DLL comes with a header file explaining how to use it. The header file defines the countless structures, enumerations, and one class that must be built using the factory method, which is accessed through the Windows ::GetProcAddress function (security through obscurity). This class contains functions that I would like to use in managed code.

I successfully completed the class in the CLI ref class and could call trivial methods on it, wrapping them.

I move on to the process of converting some structures from the header file to managed structures. For example, Native structures:

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

Included in the managed structure:

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

As far as I can tell, this should lead to the fact that the managed structure will become more flexible? And any other structure that follows a similar pattern or levels of a nested structure. Until the layout is specified and no blittable is decorated with MarshalAs, will the structure as a whole be blittable?

So I'm trying to see if there is a way to use Marshal::Copy or Marshal::PtrToStructure to convert an array of FooACL* to array<ManagedFooACL>^ .

I get an array of FooACL * from a function call; I do not highlight it myself.

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

total is the input / output that gets the size of the returned array.

What I managed to do so far, and what kind of work:

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

What I cannot think about is why this is not so:

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

This produces a:

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

Is there a way to copy array data into one call, or do I really need to do a for loop? It seems stupid with all this ability to march.

+6
source share
1 answer

Having done some more research, it seems like the answer is no. Automatically marshaling an array struct not possible without a loop.

I think the main reason struct marshaling works with PtrToStructure is that the structure is static / predefined. The compiler knows how to lay out the memory. Since you get the dynamic size of the array , there is no way to specify the memory in advance. So you have to loop the dynamic number of struct s.

Alternatively, if you knew that you would always receive an array of length X, you can define your own managed struct containing one element, namely an array ManagedFooACL with ByValArray and SizeConst value from X, and just draw a native array on struct .

+2
source

All Articles