Juliusz Hajdacki Juliusz Hajdacki - 29 days ago 20
C# Question

Native DLL - C#

I have native DLL library wrote in Delphi. I want to refer to this lib from C# and get returned string.

Function

function GetCode (aUser,aPassword: PAnsiChar): PAnsiChar; stdcall;


C# code

[DllImport("C:\\library.dll", CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi)]
private static extern String GetCode([MarshalAs(UnmanagedType.LPStr)]string aUser, [MarshalAs(UnmanagedType.LPStr)]string aPassword);

public String getCode(String login, String password) {
return GetCode(login, password);
}


Trying call function Application exits with code -1073740940 (0xc0000374).

Do you have any expirence with it? Thank you for help

Answer

With a return value of string, the marshaller assumes responsibility for freeing the returned string. It does so with a call to CoTaskMemFree. No doubt your string was not allocated on the COM heap. Hence the error, which is the NTSTATUS error code of STATUS_HEAP_CORRUPTION.

Your p/invoke should return an IntPtr instead to avoid this:

[DllImport("C:\\library.dll", CallingConvention = CallingConvention.StdCall,
    CharSet = CharSet.Ansi)]
private static extern IntPtr GetCode(string aUser, string aPassword);

To get the string, pass the return value to Marshal.PtrToStringAnsi.

public string getCode(string login, string password) 
{
    IntPtr retval = GetCode(login, password);
    string result = Marshal.PtrToStringAnsi(retval);
    // how do we deallocate retval
    return result;
}

Note also that I remove the superfluous MarshalAs attributes. CharSet.Ansi takes care of the input argument marshalling.

You still need to work out how to deallocate the returned memory. We cannot tell how it was allocated. You'll need to contact the developer of the Delphi code, or read the source. Do not be surprised if the native Delphi heap was used, which leaves you in a bind. Using the COM heap by calling CoTaskMemAlloc is actually not a bad option, and then your original p/invoke return value of string would be fine.

Other options include exporting a deallocator or asking the caller to allocate the buffer. There are a great many examples on the web of how to implement the various options.

Comments