Marshaling arrays of structs is problematic (unless they are holding
blit-able types only) in .NET, so you'll have to take care about the
marshaling yourself.
Basically what you need to do is pass the struct array as an array of
IntPtr's each pointing to an unmanaged struct, on return from unmanaged code
you'll have to marshal the IntPtr's back to their managed struct
representation.
Following illustrates the process.
// C function, takes a pointer to a pointer of type MyStruct and a ref int
holding the size of the input array
extern "C" void __declspec(dllexport) __stdcall F(Mystruct **p, int &size)
{
int n;
Mystruct * ps;
for(int n = 0; n < size; n++)
{
ps = *p++;
//set the struct fields using pointer arithmetics
ps->Id = 1;
..
}
size = n;
}
// C# snip
...
[StructLayout(LayoutKind.Sequential)]
public struct TimeTag
{
public int Day;
public int Hour;
}
[StructLayout(LayoutKind.Sequential)]
public struct Mystruct
{
public int Id;
public int Type;
public TimeTag StartTime;
public TimeTag EndTime;
public fixed int Reserved[2];
}
....
[DllImport("dllname"), SuppressUnmanagedCodeSecurity] static extern void
F( IntPtr[] p, ref int size);
....
int size = 10;
IntPtr[] ps = new IntPtr[size ];
for(int n = 0; n <size ; n++)
ps[n] =
Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Mystruc t )));
GetEmbeddedArray2(ps2, ref size );
Mystruct [] s = new Mystruct [size];
for(int i = 0; i < size ; i++)
s[i] = (Mystruct )Marshal.PtrToStructure(ps[i],
typeof(Mystruct ));
// use array of structs here...
....
Willy.
"Alexanderfe" <Alexanderfe@discussions.microsoft.comwrote in message
news:15641C49-D23B-4A21-AE13-A79C8C7EEF13@microsoft.com...
Quote:
I've forgot to mention that when I use structs that consist only of Int32
fields in the same manor, all works fine and no exception is thrown.
>
"Nicholas Paldino [.NET/C# MVP]" wrote:
>
Quote:
>Alexanderfe,
>>
> Can you give the original function and structure declaration in C?
>The
>reason I ask is because I want to know if the Reserved field on the
>MyStruct
>structure is embedded in the structure, or a pointer to another array.
>>
>>
>--
> - Nicholas Paldino [.NET/C# MVP]
> -
mvp@spam.guard.caspershouse.com
>>
>"Alexanderfe" <Alexanderfe@discussions.microsoft.comwrote in message
>news:36AEF4AB-883F-4B2D-BF33-424788C1B723@microsoft.com...
Quote:
Hi, I have a C# program that uses an unmanaged dll that has a function
similar to the signature below :
>
void f(out MyStruct[] arr, out int num); // num = actual array length
returned
>
The array must be allocated (with known max length = 10) before the
call
to
the dll function (the dll just fills it ,with no allocations).
>
The definitions of Mystruct and :
>
>
public struct Mystruct TimeTag
{
Int32 Id;
Int32 Type;
TimeTag StartTime;
TimeTag EndTime;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
Int32[] Reserved;
}
>
public struct TimeTag
{
int Day;
Int Hour;
}
>
>
I allocate the array , init all fields , allocate and init all needed
struct
fields , pass it to the dll and get an exception:
>
"The runtime has encountered a fatal error. The address of the error
was
at
0x79e95b95, on thread 0x28348. The error code is 0xc0000005. This error
may
be a bug in the CLR or in the unsafe or non-verifiable portions of user
code.
Common sources of this bug include user marshaling errors for
COM-interop
or
PInvoke, which may corrupt the stack".
>
I can't change nor the dll neither it's API.
>
What is the problem and what should I do to avoid it?
>>