Search code examples
c#c++apipinvoke

C++ API in C# with PInvoke


I have following function written in C++. How to properly declare and call it in C# using PInvoke?

SW_ErrCode SW_Connect (const char * server, int timeout, void * tag, SW_SessionID * sh_out)

In C# I have following Code:

    public enum SW_ErrCode
    {
        SWERR_Success = 0,
        SWERR_Truncated = 1,
        SWERR_Connected = 3
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct SW_SessionID
    {
        public int sessionId;
    }

    [DllImport("sw_api.dll")]
    public static extern SW_ErrCode SW_Connect(string server, int timeout, IntPtr tag, out IntPtr sh_out);

    static void Main(string[] args)
    {
        IntPtr infoPtr = new IntPtr();
        IntPtr session;          
        int b = (int)SW_Connect("", 90, infoPtr, out session);
        SW_SessionID s = (SW_SessionID)Marshal.PtrToStructure(session, typeof(SW_SessionID));
    }

I believe that the biggest problem is with "void * tag" and "SW_SessionID * sh_out". How to properly use this function?

Thanks, K


Solution

  • You are quite close. You can get the p/invoke layer to handle the returned struct. And the calling convention looks like cdecl.

    [DllImport("sw_api.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern SW_ErrCode SW_Connect(
        string server, 
        int timeout, 
        IntPtr tag,
        out SW_SessionID sh_out
    );
    

    Call it like this:

    SW_SessionID session;
    SW_ErrCode retval = SW_Connect("", 90, IntPtr.Zero, out session);
    // check retval for success
    

    I am also somewhat dubious of your use of Pack = 1. That would be very surprising if it were correct. I cannot say for sure though because you omitted much of the relevant detail.