Search code examples
c#cdllinteropmarshalling

Why is this String empty when invoking/marshaling this struct from C# to C-DLL?


I got a function like this defined in a C-DLL:

int AcquireArchive (char* archiveName, Password* password)

The struct Password is defined in the DLL as:

typedef struct password {
unsigned char* pPwd;
unsigned long length;
} Password;

What I am doing is trying to wrap this function in C# using:

[DllImport("name.dll", CharSet = CharSet.Ansi, EntryPoint = "_AcquireArchive@16", 
CallingConvention = CallingConvention.StdCall)]
public static extern int AcquireArchive(
[MarshalAs(UnmanagedType.LPStr)] string archiveName, 
ref Password password
);

and:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Password
{ 
    public string pwd;
    public ulong length;
}

I call this function by:

Password password;
password.pwd = "password";
password.length = (ulong)password.pwd.Length;

int code = AcquireArchive("Archive", ref password);

Now the problem is that the returned code signals INVALID PASSWORD, indicating (according to the documentation) a password-length of 0. Is it possible the value of password.pwd and/or password.length get lost in the invocation/marshalling process?

Sadly I don't have access to the source-code of the dll.

EDIT: CharSet is now Ansi, TYPO "length", removed [UnmanagedType.BStr]


Solution

  • at least one problem I see:
    in your C Code (length is 32 or 64 bit depending to the DLL):

    typedef struct {
      unsigned char* pPwd;
      unsigned long length;
    } Password;
    

    and in your C# code(length is 64 bit):

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct Password
    { 
        public string pwd;
        public ulong length;
    }
    

    if it is 64 bit , it is OK. but if it is 32 bit, you should change your C# ulong to uint like this:

    public struct Password
    {
        public string pwd;
        public uint length;
    }  
    

    I hope this helps.