Pinvoke Marshal char** RRS feed

  • Question

  • I have a c DLL function which exposes the following declaration:

    typedef int extern CredentialsCallback(char **pUsername, char **pPassword);

    I would like to use it in c#, I try the following declaration but it seems to be wrong:

    public delegate Int32 CredentialsCallback(ref String pUsername, ref String pPassword)

    Can anyone help ?

    Wednesday, August 13, 2008 12:58 PM


  • There are two possible scenarios here.  The first one is where the unmanaged code has allocated a string buffer for you to write in.  That seems a bit unlikely, it doesn't tell you how large that buffer is.  With some luck, it is large enough and you'd declare the argument as "IntPtr pUsername" and do this:

        string username = "bla";
        byte[] ascii = Encoding.ASCII.GetBytes(username);
        Marshal.Copy(ascii, 0, pUsername, ascii.Length);

    You'll get an AccessViolation exception if this isn't the correct scenario or if the unmanaged code allocated a buffer that was too small.  You could also silently corrupt memory if the buffer was too small.  You should try a different encoding (like Default) if you have trouble with accented characters.

    The second scenario, the more likely one, is that the unmanaged code expects you to return a pointer to a string.  You should declare the arguments as "out IntPtr", then return the string with

      pUsername = Marshal.StringToCoTaskMemAnsi("bla").

    Problem is, it isn't very likely that the unmanaged code will know how to properly release the string buffer.  It should use CoTaskMemFree() but I bet it just uses free().  You'll leak memory every time it is called.  Or get an AV when it tries to release the buffer.

    All and all, the chance for random failure is quite high.

    Hans Passant.
    • Marked as answer by jack 321 Monday, August 18, 2008 4:02 AM
    Thursday, August 14, 2008 12:24 PM