views:

163

answers:

2

I have the following C function:

int w_ei_connect_init(ei_cnode* ec, const char* this_node_name, 
                      const char *cookie, short creation);

ei_cnode looks like this:

typedef struct ei_cnode_s {
    char thishostname[EI_MAXHOSTNAMELEN+1];
    char thisnodename[MAXNODELEN+1];
    char thisalivename[EI_MAXALIVELEN+1];
    char ei_connect_cookie[EI_MAX_COOKIE_SIZE+1];
    short creation;
    erlang_pid self;
} ei_cnode;

Which I have converted to C#:

[StructLayout(LayoutKind.Sequential)]
public struct cnode {
    [MarshalAsAttribute(UnmanagedType.ByValTStr, 
        SizeConst = Ei.MAX_HOSTNAME_LEN + 1)]
    public string thishostname;
    [MarshalAsAttribute(UnmanagedType.ByValTStr, 
        SizeConst = Ei.MAX_NODE_LEN + 1)]
    public string thisnodename;
    [MarshalAsAttribute(UnmanagedType.ByValTStr, 
        SizeConst = Ei.MAX_ALIVE_LEN + 1)]
    public string thisalivename;
    [MarshalAsAttribute(UnmanagedType.ByValTStr, 
        SizeConst = Ei.MAX_COOKIE_SIZE + 1)]
    public string ei_connect_cookie;
    public short creation;
    public erlang_pid self;
}

I'm not good with pointers or C in general, so I'm not sure how I'm supposed to supply a cnode to ei_connect_init.

What would the equivalent C# signature be for the C function above?

+1  A: 

Something like this should work:


int w_ei_connect_init(ref cnode ec, 
         [MarshalAs(UnmanagedType.LPStr)] string this_node_name, 
         [MarshalAs(UnmanagedType.LPStr)] string cookie, short creation);

You should also consider marking your struct with

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]

attribute, so those TStr will be ansi-strings, not unicode.

Ravadre
Perfect! Thanks!
David Brown
+2  A: 

Whenever you want to pass a C# struct to a parameter value containing the equivalent native struct but with a pointer, the typical method is to label the parameter as "ref". This causes the PInvoke layer to essentially pass the address in.

[DllImport("somedll")]
public static extern w_ei_connect_init(
  ref cnode v,
  [In] string this_node_name,
  [In] string cookie,
  int16 creation);
JaredPar
So I don't need the MarshalAsAttributes?
David Brown
@David, no not in this case because the defaults are correct. Although it's probably better to add them to be explicit.
JaredPar