The dll is written in c++ and sends text as utf8 through aconst char* callback.
First, is this the correct way to declare the callback?
[UnmanagedFunctionPointer( CallingConvention.StdCall )]public delegate void TextCallback( string sText );[DllImport( "cppLib.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl )]public static extern void GetText( [MarshalAs( UnmanagedType.FunctionPtr )] TextCallback textCallback );private TextCallback m_TextCallback;Native callback:
typedef void ( __stdcall * TextCallback )( const char* szText );If so, how do I handle the utf8 text once it arrives?
I'm sending it to a RichTextBox and the utf8 chars come out as garbage (the ones that happen to be ascii print fine).
Thank you all.
ANSWER
In the comments below, TheUndeadFish provided alink with an answer that works. It is also explained to a degree. Those interested should take a look. I'm just replicating the answer here as it applies to the code I posted.
Only this modification is needed:
[UnmanagedFunctionPointer( CallingConvention.StdCall )]public delegate void TextCallback( IntPtr ipText );The delegate reinterprets the int pointer (pointing to a utf8 string from the c++ dll) as follows:
m_TextCallback = ( ipText ) =>{ var data = new System.Collections.Generic.List<byte>(); var off = 0; while( true ) { var ch = Marshal.ReadByte( ipText, off++ ); if( ch == 0 ) { break; } data.Add( ch ); } string sptr = Encoding.UTF8.GetString( data.ToArray() );};- What is the signature of the native callback?Marcel N.– Marcel N.2014-08-04 21:03:27 +00:00CommentedAug 4, 2014 at 21:03
- 1The first google result for "dllimport charset utf-8" isblog.kutulu.org/2012/04/… which looks quite relevant. I quickly skimmed it and its conclusion appears to be that the CharSet attribute doesn't handle conversion to/from UTF-8.TheUndeadFish– TheUndeadFish2014-08-04 23:13:21 +00:00CommentedAug 4, 2014 at 23:13
- @TheUndeadFish. My heartfelt thanks were removed for some reason.user1908746– user19087462014-08-05 01:39:51 +00:00CommentedAug 5, 2014 at 1:39
1 Answer1
You should use CharSet.Unicode (if the string is a wchar*, 2 bytes per char) or CharSet.Ansi (if the string is 1 byte per char).
Since your string is in UTF8, you should convert by hand. None of the default conversion fit your problem.
