Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Marshaling c# call to DLL library

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.

like image 527
vbisbest Avatar asked Jan 08 '18 18:01

vbisbest


People also ask

What is marshaling in C#?

Marshalling is the process of transforming types when they need to cross between managed and native code. Marshalling is needed because the types in the managed and unmanaged code are different.

What is meant by marshaling?

transitive verb. : to place in proper rank or position. marshaling the troops. : to bring together and order in an appropriate or effective way. marshal arguments.

Is it marshaling or marshalling?

Marshaling and marshalling are both English terms. In the United States, there is a 80 to 20 preference for "marshalling" over "marshaling".

What is marshaling in distributed systems?

Marshalling: Marshalling is the process of transferring and formatting a collection of data structures into an external data representation type appropriate for transmission in a message.


1 Answers

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

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

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

And numerous other Google searches for the types in question.

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)]
        public 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)]
        public 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;
        };




        [StructLayout(LayoutKind.Explicit, Size = 16)]
        public struct in6_addr_u
        {
            [FieldOffset(0)]
            public byte Byte0;
            [FieldOffset(1)]
            public byte Byte1;
            [FieldOffset(2)]
            public byte Byte2;
            [FieldOffset(3)]
            public byte Byte3;
            [FieldOffset(4)]
            public byte Byte4;
            [FieldOffset(5)]
            public byte Byte5;
            [FieldOffset(6)]
            public byte Byte6;
            [FieldOffset(7)]
            public byte Byte7;
            [FieldOffset(8)]
            public byte Byte8;
            [FieldOffset(9)]
            public byte Byte9;
            [FieldOffset(10)]
            public byte ByteA;
            [FieldOffset(11)]
            public byte ByteB;
            [FieldOffset(12)]
            public byte ByteC;
            [FieldOffset(13)]
            public byte ByteD;
            [FieldOffset(14)]
            public byte ByteE;
            [FieldOffset(15)]
            public byte ByteF;

            [FieldOffset(0)]
            public UInt16 Word0;
            [FieldOffset(2)]
            public UInt16 Word1;
            [FieldOffset(4)]
            public UInt16 Word2;
            [FieldOffset(6)]
            public UInt16 Word3;
            [FieldOffset(8)]
            public UInt16 Word4;
            [FieldOffset(10)]
            public UInt16 Word5;
            [FieldOffset(12)]
            public UInt16 Word6;
            [FieldOffset(14)]
            public UInt16 Word7;
        }

        [StructLayout(LayoutKind.Explicit, Size = 16)]
        public struct in6_addr
        {
            [FieldOffset(0)]
            public in6_addr_u u;
        }


        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct sockaddr_in6
        {
            public UInt64  sin6_len;            //  length of this struct(sa_family_t)

            public UInt32  sin6_family;         //  AF_INET6 (sa_family_t)

            public UInt16   sin6_port;          //  Transport layer port # (in_port_t)

            public UInt32   sin6_flowinfo;      //  IP6 flow information

            public in6_addr sin6_addr;          //  IP6 address

            public UInt32   sin6_scope_id;      //  scope zone index
        };


        [StructLayout(LayoutKind.Explicit, Size = 16)]
        public struct res_sockaddr_union
        {
            [FieldOffset(0)]
            public sockaddr_in sin;

            [FieldOffset(0)]
            public sockaddr_in6 sin6;

            [FieldOffset(0)]
            public Int64 __align64;

            [FieldOffset(0)]
            public Int32 __align32;

            // This is the char __space[128] bit.
            // I've cheated and used 16 8 byte values.
            [FieldOffset(0)]
            public UInt64 __space0;
            [FieldOffset(8)]
            public UInt64 __space1;
            [FieldOffset(16)]
            public UInt64 __space2;
            [FieldOffset(24)]
            public UInt64 __space3;
            [FieldOffset(32)]
            public UInt64 __space4;
            [FieldOffset(40)]
            public UInt64 __space5;
            [FieldOffset(48)]
            public UInt64 __space6;
            [FieldOffset(56)]
            public UInt64 __space7;
            [FieldOffset(64)]
            public UInt64 __space8;
            [FieldOffset(72)]
            public UInt64 __space9;
            [FieldOffset(80)]
            public UInt64 __spaceA;
            [FieldOffset(88)]
            public UInt64 __spaceB;
            [FieldOffset(96)]
            public UInt64 __spaceC;
            [FieldOffset(104)]
            public UInt64 __spaceD;
            [FieldOffset(112)]
            public UInt64 __spaceE;
            [FieldOffset(120)]
            public UInt64 __spaceF;
        }



        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;
        }
    }
}

Best I can do - don't feel under pressure to accept the answer if it doesn't solve your issue but please do take some time to try to understand what's going on in the example I've given you.

I haven't had chance to test it - but it does build.

Good luck!

Regards,

Adam.

like image 143
Adam Benson Avatar answered Oct 04 '22 04:10

Adam Benson