Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# callback receiving UTF8 string

I have a C# function, a callback, called from a Win32 DLL written in C++. The caller gives me a UTF8 string, but I can't receive it properly, all the hungarian special characters go wrong.

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int func_writeLog(string s);

When I changed the parameter type to IntPtr, and wrote the code, it writes properly. But I find this is a very slow solution:

        byte[] bb = new byte[1000];
        int i = 0;
        while (true)
        {
            byte b = Marshal.ReadByte(pstr, i);
            bb[i] = b;
            if (b == 0) break;
            i++;
        }
        System.Text.UTF8Encoding encodin = new System.Text.UTF8Encoding();
        var sd = encodin.GetString(bb, 0, i);

I tried to write some attribute to string parameter, like:

  [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  public delegate int func_writeLog([In, MarshalAs(UnmanagedType.LPTStr)] string s);

no one was working. Any advice please? Thanks in advance!

like image 507
Zoltan Hernyak Avatar asked Aug 30 '12 10:08

Zoltan Hernyak


1 Answers

There's no decent way to do this fast in pure managed code, it always requires copying the string and that's very awkward because you don't know the required buffer size. You'll want to pinvoke a Windows function to do this for you, MultiByteToWideChar() is the work-horse converter function. Use it like this:

using System.Text;
using System.Runtime.InteropServices;
...
    public static string Utf8PtrToString(IntPtr utf8) {
        int len = MultiByteToWideChar(65001, 0, utf8, -1, null, 0);
        if (len == 0) throw new System.ComponentModel.Win32Exception();
        var buf = new StringBuilder(len);
        len = MultiByteToWideChar(65001, 0, utf8, -1, buf, len);
        return buf.ToString();
    }
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern int MultiByteToWideChar(int codepage, int flags, IntPtr utf8, int utf8len, StringBuilder buffer, int buflen);
like image 134
Hans Passant Avatar answered Sep 23 '22 04:09

Hans Passant