1

I have a embeded record in delphi like this:

TKernel = packed record
    State: Integer;
end;
TKernels = array[0..19] of TKernel;

TShell = packed record
  Kernels: TKernels;
end;

In this,

SizeOf(TShell) = 20 * SizeOf(TKernel).

But If I use C#:

struct Shell
{
    Kernel[] Kernels;
    public Shell(int i = 20)
    {
        Kernels = new Kernel[20];
    }
}

then: Marshal.SizeOf(Shell) == 4

that means Kernels is just a pointer. I want to InterOp C# with Delphi, so I need there memory structure is the same, So how should I declare the struct in C# besides write 20 likes of Kernel KernelOne; Kernel KernelTwo。。。

2 Answers 2

7

I would always avoid unsafe if at all possible since unsafe code is, well, not safe. And it is quite possible to avoid in this case:

[StructLayout(LayoutKind.Sequential, Pack=1)]
struct Kernel
{
    int State;
}

[StructLayout(LayoutKind.Sequential, Pack=1)]
struct Shell
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=20)]
    Kernel[] Kernels;
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks David; like Richard Schneider, I learned something new today. I'm curious though: the declarations above cause the type to have a size of 80 (reported by Marshal.SizeOf), but Kernels has a default value of null, and it's possible to assign a Kernel[] of any length. So the managed type is obviously a normal managed type. Do you know how that's marshalled (especially if the managed array is of the wrong length)? Do you know where this is documented? There's not much detail at msdn.microsoft.com/en-us/library/z6cfh6e6(v=vs.100).aspx. Thanks again!
Extra items will be truncated. Missing items will be marshalled using default values.
4

You can do this in unsafe code with the fixed keyword:

unsafe struct Shell
{
    public fixed Kernel Kernels[20];
}

EDIT

This use of fixed was added in C# 2.0, according to the documentation for "fixed size buffers."

EDIT 2

And, oops, you can only created fixed-size buffers of a primitive type; as the documentation states, "the only restriction is that the array type must be bool, byte, char, short, int, long, sbyte, ushort, uint, ulong, float, or double"

3 Comments

@RichardSchneider thanks :-) I added a link to the documentation, in case you are interested.
@phoog Thanks. But esides unsafe code, any thing "safe" in case the assembly can not be build using /unsafe?
@RichardSchneider investigating David Heffernan's solution, I found that fixed-sized buffers are limited to certain primitive types. :( See the edited post for details.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.