2013-05-25 11 views
5

私は他の言語(java、C#、python)へのバインディングを持つポータブルC++ライブラリを作成しています。私はSWIGの助けを借りてバインディングを作っています。SWIGはC#でutf8文字列を処理する方法は?

私はC++で書かれたクラスがあります。

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

をそして、私はC#の側にそのようなものを持っている:それはUTF8をしないことを除いて

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

SWIGは、十分にすべてを行い< => MyClassの呼び出し中のutf16文字列の変換。

これで何ができますか?カスタムタイプマップを書くのはちょっと複雑に見えますが、それが唯一の解決策であれば、私はそれに助けが必要です。

答えて

4

私はmy own very similar questionと答えることができました。私は(これはテストしていませんが)あなたの状況にも変化がないと思います。唯一の違いは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; 
    } 
} 

その後、ガブガブ飲むの "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" 

すべてが動作します。リンクされた記事を読んで、これがどのように機能するかをよく理解してください。

関連する問題