如何让SWIG处理C#中的utf8字符串?

我正在编写一个可移植的C ++库,它绑定到其他语言(java,C#,python)。 我正在SWIG的帮助下制作那些绑定。

我有一个用C ++编写的类:

class MyClass { public: const char* get_value() const; // returns utf8-string void set_value(const char* value); // gets utf8-string private: // ... }; 

我在C#方面有类似的东西:

 public class MyClass { public string get_value(); public void set_value(string value); } 

SWIG做得很好,除了它在调用MyClass期间没有进行utf8 utf16字符串转换。

我该怎么办? 编写自定义类型映射看起来有点复杂,如果它是唯一可用的解决方案,我需要帮助。

我能够回答我自己非常相似的问题 ,如下所示。 我认为(虽然我没有测试过)这可能对你的情况有效,没有任何变化。 唯一的区别是我正在使用std :: string,而你正在使用char *,但我认为SWIG已经以同样的方式对待它们了。

在David Jeske的链接代码项目文章的帮助下(阅读:天才!),我终于能够回答这个问题了。

你需要在C#库中使用这个类(来自David Jeske的代码)。

 public class UTF8Marshaler : ICustomMarshaler { static UTF8Marshaler static_instance; public IntPtr MarshalManagedToNative(object managedObj) { if (managedObj == null) return IntPtr.Zero; if (!(managedObj is string)) throw new MarshalDirectiveException( "UTF8Marshaler must be used on a string."); // not null terminated byte[] strbuf = Encoding.UTF8.GetBytes((string)managedObj); IntPtr buffer = Marshal.AllocHGlobal(strbuf.Length + 1); Marshal.Copy(strbuf, 0, buffer, strbuf.Length); // write the terminating null Marshal.WriteByte(buffer + strbuf.Length, 0); return buffer; } public unsafe object MarshalNativeToManaged(IntPtr pNativeData) { byte* walk = (byte*)pNativeData; // find the end of the string while (*walk != 0) { walk++; } int length = (int)(walk - (byte*)pNativeData); // should not be null terminated byte[] strbuf = new byte[length]; // skip the trailing null Marshal.Copy((IntPtr)pNativeData, strbuf, 0, length); string data = Encoding.UTF8.GetString(strbuf); return data; } public void CleanUpNativeData(IntPtr pNativeData) { Marshal.FreeHGlobal(pNativeData); } public void CleanUpManagedData(object managedObj) { } public int GetNativeDataSize() { return -1; } public static ICustomMarshaler GetInstance(string cookie) { if (static_instance == null) { return static_instance = new UTF8Marshaler(); } return static_instance; } } 

然后,在Swig的“std_string.i”中,在第24行替换此行:

 %typemap(imtype) string "string" 

用这一行:

 %typemap(imtype, inattributes="[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]", outattributes="[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]") string "string" 

在第61行,替换此行:

 %typemap(imtype) const string & "string" 

用这一行:

 %typemap(imtype, inattributes="[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]", outattributes="[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]") string & "string" 

瞧,一切正常。 阅读链接的文章,以便更好地了解其工作原理。