The problem with this is that the C# marshaller passes a temporary block of memory into the function as aName
. This memory is the destroyed when the function returns. But you are also asking the C# marshaller to marshal this same block of memory into a C# string.
It's not good practice to return a null-terminated string from a native DLL function anyway. You have a couple of options:
- Use a
StringBuilder
on the C# side to pre-allocate the memory for the string. This requires you to get hold of the required size somehow. This is the most common way to interop strings.
- Return the string as a COM
BSTR
and the C# marshaller knows how to marshall and dispose a BSTR
, and has access to the COM allocator to do so. I have no knowledge about using BSTR
in FreePascal but in Delphi you simply use WideString
. You also need to tell the C# marshaller that you are returning a BSTR
.
I personally have a preference for option 2. There is one wrinkle though and that is that different compilers use a different ABI for function return values, as discussed at this question: Why can a WideString not be used as a function return value for interop? The easy way around that is to return the string in a parameter rather than using the function return value.
The code looks like this:
Pascal
procedure Encrypt(Input: WideString; out Output: WideString); stdcall;
begin
Output := Input;
end;
C#
[DllImport("project1.dll")]
public static extern void Encrypt(
[MarshalAs(UnmanagedType.BStr)] string input;
[MarshalAs(UnmanagedType.BStr)] out string output
);