2013-05-25 5 views
5

मैं एक पोर्टेबल सी ++ लाइब्रेरी लिख रहा हूं जिसमें बाइंडिंग अन्य भाषाओं (जावा, सी #, पायथन) के साथ है। मैं SWIG की सहायता से उन बाइंडिंग कर रहा हूं।सी # में utf8 तारों के साथ SWIG सौदे कैसे करें?

मैं एक वर्ग C++ लिखा है:

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

और मैं सी # तरफ ऐसा ही कुछ है:

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

बड़ा घूँट सब कुछ अच्छी तरह से करता है, सिवाय इसके कि यह एक UTF8 नहीं है < => MyClass को कॉल के दौरान utf16 स्ट्रिंग रूपांतरण।

मैं इसके साथ क्या कर सकता हूं? एक कस्टम टाइपमैप लिखना थोड़ा जटिल लगता है, और मुझे इसके साथ मदद की ज़रूरत है यदि यह एकमात्र उपलब्ध समाधान है।

उत्तर

4

मैं निम्नानुसार my own very similar question का उत्तर देने में सक्षम था। मुझे लगता है (हालांकि मैंने परीक्षण नहीं किया है) कि यह आपकी स्थिति के लिए भी कोई बदलाव नहीं कर सकता है। केवल अंतर यह है कि मैं std :: स्ट्रिंग का उपयोग कर रहा हूं, और आप char * का उपयोग कर रहे हैं, लेकिन मुझे लगता है कि SWIG पहले से ही इन तरीकों से व्यवहार करता है।

लिंक कोड कोड आलेख में 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, inattributes="[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]", outattributes="[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]") string "string" 

और लाइन 61 पर, इस लाइन को बदल दें: इस लाइन के साथ

%typemap(imtype) string "string" 

:

%typemap(imtype) const string & "string" 

इस लाइन के साथ:

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

लो और देखें, सबकुछ काम करता है। यह कैसे काम करता है इसकी अच्छी समझ के लिए लिंक किए गए आलेख को पढ़ें।

संबंधित मुद्दे