[Mono-list] unmanaged type limitations -- no unmanaged arrays?

David Jeske jeske@chat.net
Sat, 12 Jul 2003 08:57:22 -0700


This time I have some PInvoke information to share, so that when
someone else runs into this issue they can see what I've done.

In my ClearSilver (www.clearsilver.net, an HTML template system) C#
wrapper, I wanted to access this C-struct:

typedef struct _neo_err
{
  int error;
  int err_stack;
  int flags;
  char desc[256];
  const char *file;
  const char *func;
  int lineno;
  /* internal use only */
  struct _neo_err *next;
} NEOERR;

My philosophy of using unsafe struct pointers, and just accessing the
struct out in unmanaged memory is great, and it's exactly what I want
to do. However, handling "char dest[256]" is not straightforward.

In C# arrays are reference types. Using one makes the struct a managed
type, and I can't put the array size in. The following is conceptually
what I want to do, however, it's obviously invalid:

[StructLayout(LayoutKind.Sequential)]
unsafe struct NEOERR {
  public int error;
  public int err_stack;
  public int flags;
  public byte[256] desc;  // this is invalid, can't contain size
  public const byte *file; 
  public const byte *func; 
  public int lineno;

  /* internal use only */
  private NEOERR *next;
};

This dosn't work either:

  [ MarshalAs( UnmanagedType.LPStr, SizeConst=256 )] 
    public string desc; 
    
Because in this case, I don't want to marshal the data. I just want to
talk to it in place. The solution I could come up with is this:

[StructLayout(LayoutKind.Explicit)]
unsafe struct NEOERR {
  [FieldOffset(0)] public int error;
  [FieldOffset(4)] public int err_stack;
  [FieldOffset(8)] public int flags;
  // public byte[256] dest;  // not representable
  [FieldOffset(12)] public byte dest_first_char; // use this as an address??
  [FieldOffset(268)] public byte *file; // const
  [FieldOffset(272)] public byte *func; // const
  [FieldOffset(276)] public int lineno;
};

UGH! First, this is obviously annoying. Second, the only way I can
figure to get access to "char dest[256]" is to use "char* dest =
&nerr->dest_first_char;" and then just use dest as a pointer to the
string. I've dug through the documentation, and I can't find any
better solution.

Obviously it would be ideal if there were a way to represent a
value-type array. I wonder how Managed C++ handles "char foo[256];" in
a struct.

Anyhow, I'm not expecting a reply to this message, as I don't think
there is any great solution to this. I just figured it might be
interesting to someone else.

-- 
David Jeske (N9LCA) + http://www.chat.net/~jeske/ + jeske@chat.net