"Explicit String Marshalling Example (C# Side)"

// C#
 
[DllImport(NATIVE_DLL_NAME, CallingConvention = CallingConvention.Cdecl,
    EntryPoint = "GetErrorStrLen")]
public static extern uint GetErrorStrLen();
 
[DllImport(NATIVE_DLL_NAME, CallingConvention = CallingConvention.Cdecl,
    EntryPoint = "GetErrorStr")]
public static extern uint GetErrorStr(
    IntPtr strSpace
);
 
public static unsafe void Test() {
        int errorStrLen = (int) GetErrorStrLen();
        char* errorStr = stackalloc char[errorStrLen + 1]; // +1 for the null terminator
        GetErrorString((IntPtr) errorStr);
        string errorString = Marshal.PtrToStringUni((IntPtr) errorStr);
}


Code snippet taken from "P/Invoke Tips".