[Xapian-discuss] German Danish Russian

win 32 win32ster at gmail.com
Wed Sep 2 12:16:07 BST 2009


All right, as I understand the default Windows .NET marshalling doesn’t work
as it translates CSharp Unicode strings to the user default ANSI charset
(Russian in my case) and it is UTF-8, not ANSI what Xapian wants. So I wrote
a custom marshaller to perform Unicode -> UTF-8 -> Unicode conversions:

class UTF8StringMarshaler : ICustomMarshaler
{
private static UTF8StringMarshaler marshaler = null;
public static ICustomMarshaler GetInstance(string cookie)
{
if (marshaler == null)
marshaler = new UTF8StringMarshaler();
return marshaler;
}

public IntPtr MarshalManagedToNative(Object ManagedObj)
{
if (!(ManagedObj is string))
throw new ArgumentException("The passed object is not a string",
"ManagedObj");
byte[] unicodeBytes = Encoding.Unicode.GetBytes((string)ManagedObj);
byte[] utf8Bytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF8,
unicodeBytes);
IntPtr result = Marshal.AllocHGlobal(utf8Bytes.Length + 1);
Marshal.Copy(utf8Bytes, 0, result, utf8Bytes.Length);
Marshal.WriteByte(result, utf8Bytes.Length, 0);
return result;
}

public void CleanUpNativeData(IntPtr pNativeData)
{
Marshal.FreeHGlobal(pNativeData);
}

public int GetNativeDataSize()
{
return 0;
}

public Object MarshalNativeToManaged(IntPtr pNativeData)
{
int length;
for (length = 0; Marshal.ReadByte(pNativeData, length) != 0; length++) ; //
get unmanaged string length
byte[] utf8Bytes = new byte[length];
Marshal.Copy(pNativeData, utf8Bytes, 0, length);
return Encoding.UTF8.GetString(utf8Bytes);
}

public void CleanUpManagedData(Object ManagedObj)
{
}
} // class UTF8StringMarshaler

Then I just broke incapsulation of the classes that I used to get pointers
to C++ objects and called the corresponding c++ dll entries like

[DllImport("_XapianSharp", EntryPoint = "CSharp_Query_GetDescription")]
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef =
typeof(UTF8StringMarshaler))]
public static extern string Query_GetDescription(HandleRef jarg1);

public static string GetDescriptionU(this Xapian.Query query)
{
string ret = Query_GetDescription(query.swigCPtr);
if (Xapian.XapianPINVOKE.SWIGPendingException.Pending) throw
Xapian.XapianPINVOKE.SWIGPendingException.Retrieve();
return ret;
}

[DllImport("_XapianSharp", EntryPoint =
"CSharp_QueryParser_ParseQuery__SWIG_0")]
static extern IntPtr QueryParser_ParseQuery__SWIG_0(HandleRef jarg1,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef =
typeof(UTF8StringMarshaler))] string jarg2,
uint jarg3,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef =
typeof(UTF8StringMarshaler))] string jarg4);

public static Xapian.Query ParseQueryU(this Xapian.QueryParser queryParser,
string query_string, uint flags, string default_prefix)
{
Xapian.Query ret;
ret = new Xapian.Query(QueryParser_ParseQuery__SWIG_0(queryParser.swigCPtr,
query_string, flags, default_prefix), true);
if (Xapian.XapianPINVOKE.SWIGPendingException.Pending) throw
Xapian.XapianPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
}

Maybe sombody custom with SWIG can create interface file for windows .net
using my marshaler code and the stated declaration attributes to generate
proper XapianPINVOKE.cs? I just get a bit lost in the heap of files although
will keep searching.


More information about the Xapian-discuss mailing list