Sascha G Sascha G - 4 months ago 21
C Question

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]

Amd Amd
Answer

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.

Comments