Thursday, January 18, 2018

Marshaling c# call to DLL library

Leave a Comment

I am having trouble calling a DLL library with a specific signature. This is on the xamarin platform and running on iOS. I am trying to get a list of DNS servers. I can call other functions without an issue, but the one I really need is not working. I am sure its becuase my struct is not correct. I believe the issue is the "union" type. I just dont know what my struct should look like to appease that parameter. Here are the relevant c++ types:

1: The DLL singature

`int res_getservers __P((res_state, union res_sockaddr_union * , int));` 

2: The c++ structs

union res_sockaddr_union {     struct sockaddr_in  sin; #ifdef IN6ADDR_ANY_INIT     struct sockaddr_in6 sin6; #endif #ifdef ISC_ALIGN64     int64_t         __align64;  /* 64bit alignment */ #else     int32_t         __align32;  /* 32bit alignment */ #endif     char            __space[128];   /* max size */ };   struct sockaddr_in6 {     __uint8_t   sin6_len;   /* length of this struct(sa_family_t) */     sa_family_t sin6_family;    /* AF_INET6 (sa_family_t) */     in_port_t   sin6_port;  /* Transport layer port # (in_port_t) */     __uint32_t  sin6_flowinfo;  /* IP6 flow information */     struct in6_addr sin6_addr;  /* IP6 address */     __uint32_t  sin6_scope_id;  /* scope zone index */ };  struct sockaddr_in {     __uint8_t   sin_len;     sa_family_t sin_family;     in_port_t   sin_port;     struct  in_addr sin_addr;     char        sin_zero[8]; }; 

Any help on generating the proper c# structs would be greatly appreciated! Thank you.

1 Answers

Answers 1

Disclaimer: I don't have C++ installed on my machine any more but I believe this will either work, or at least give you a good shove in the right direction.

Based on: https://msdn.microsoft.com/en-us/library/windows/desktop/ms738571(v=vs.85).aspx

typedef struct in_addr {   union {     struct {       u_char s_b1,s_b2,s_b3,s_b4;     } S_un_b;     struct {       u_short s_w1,s_w2;     } S_un_w;     u_long S_addr;   } S_un; } IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR; 

And: https://docs.microsoft.com/en-us/cpp/mfc/reference/sockaddr-in-structure

struct sockaddr_in{       short sin_family;       unsigned short sin_port;   struct in_addr sin_addr;       char sin_zero[8];   };   

And: https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.structlayoutattribute(v=vs.110).aspx

using System; using System.Runtime.InteropServices;  namespace SockStructTest {     class Program     {         [StructLayout(LayoutKind.Explicit, Size = 8)]         public struct struct_sin_zero         {             [FieldOffset(0)]             public byte s_b1;             [FieldOffset(1)]             public byte s_b2;             [FieldOffset(2)]             public byte s_b3;             [FieldOffset(3)]             public byte s_b4;             [FieldOffset(4)]             public byte s_b5;             [FieldOffset(5)]             public byte s_b6;             [FieldOffset(6)]             public byte s_b7;             [FieldOffset(7)]             public byte s_b8;              [FieldOffset(0)]             public UInt64 s_ui64;         };            [StructLayout(LayoutKind.Explicit, Size = 4)]         struct in_addr         {             [FieldOffset(0)]             public byte s_b1;             [FieldOffset(1)]             public byte s_b2;             [FieldOffset(2)]             public byte s_b3;             [FieldOffset(3)]             public byte s_b4;              [FieldOffset(0)]             public UInt16 s_w1;             [FieldOffset(2)]             public UInt16 s_w2;              [FieldOffset(0)]             public UInt32 S_addr;         };           [StructLayout(LayoutKind.Explicit, Size = 16)]         struct sockaddr_in         {             [FieldOffset(0)]             public Int16 sin_family;              [FieldOffset(2)]             public UInt16 sin_port;              [FieldOffset(4)]             public in_addr sin_addr;                [FieldOffset(8)]             public struct_sin_zero sin_zero;         };           static void Main(string[] args)         {             sockaddr_in ad;              ad.sin_zero.s_ui64 = 0;              ad.sin_family = 0; // or whatever              ad.sin_port = 1234;              // Address as b bit values             ad.sin_addr.s_b1 = 0;             ad.sin_addr.s_b2 = 1;             ad.sin_addr.s_b3 = 2;             ad.sin_addr.s_b4 = 3;              // Address as 16 bits             ad.sin_addr.s_w1 = 0;             ad.sin_addr.s_w2 = 0;         }     } } 

If it doesn't work, let me know and I'll try to tweak it. Might even install C++ and try passing it to a library to ensure it arrives in the right format.

Just one basic question you probably ought to think about: are you absolutely sure there are no higher level libs you could be using that would make your life a little easier? It's been a long while since I did any TCP/IP programming at such a low level - because now there are libs that usually shield you from needing to get your hands this dirty.

Anyway, hope this helps. Note: I've only done the TCP V4 structs. See if they work and if they do what I've done ought to help you with the rest. If it doesn't get back to me.

Regards,

Adam.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment