Search code examples
c#c++dllwchar-tinteropservices

How convert const wchar_t* from C DLL to C# string automatically


It is just a curiosity. Perhaps there is a person in this world who did such things:

I have to export C function and load it from C# code via DllImport

const wchar_t * SysGetLibInfo() {
    return dllmanager.SysGetLibInfo();
}

The best things to do that, and it is recommended widely, is to declare IntPtr and then convert it to string using some function. In other words, something like this

[DllImport(dll, CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr SysGetLibInfo(); 
// ...
Marshal.PtrToStringUni(SysGetLibInfo());

This approach works. But Is there a way to do that automatically? To make SysGetLibInfo to be returning a string? I found some suggestions like this:

[DllImport(dll, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPWStr)]
private static extern string SysGetLibInfo();

But it doesn't work, and, according to a variety of examples and scant reports it should not work.

Is there a way to write my own attribute like MarshalAs which will convert IntPtr to string? Something similar to this:

[DllImport(dll, CallingConvention = CallingConvention.Cdecl)]
[return: MyOwnMarshalPtrToStringUni]
private static extern string SysGetLibInfo();

Thanks in advance for any information or useful links, examples, books. Again, it is just a curiosity.

P.S. Suggestion to wrap SysGetLibInfo with a separate function which convert result to string using PtrToStringUni is not an option ;)


Solution

  • You can't override MarshalAs but you can use custom marshalling instead

    http://msdn.microsoft.com/en-us/library/w22x2hw6.aspx

      [DllImport(dll, CallingConvention = CallingConvention.Cdecl)]
      [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(MyMarshaller))]
      private static extern string SysGetLibInfo();