[Mono-list] Need help with DllImport (P/Invoke) and UCS-4 unicode
Jonathan Pryor
jonpryor at vt.edu
Mon Jul 16 06:08:04 EDT 2007
On Mon, 2007-07-16 at 02:57 +0200, Christian Heimes wrote:
> One of the problematic function look like:
>
> [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl,
> EntryPoint = "PyUnicodeUCS4_FromUnicode",
> ExactSpelling = true, CharSet = CharSet.Unicode)]
> internal unsafe static extern IntPtr
> PyUnicode_FromUnicode(string s, int size);
>
> More functions can be found at
> https://pythonnet.svn.sourceforge.net/svnroot/pythonnet/branches/clr-2.0-python-2.5-branch/src/runtime/runtime.cs
>
> How should I solve the issue? Has Mono some generic solution for the
> general issue of UCS-4 vs. UCS-2 unicode
No.
> or do I have to convert the
> stuff manually by wrapping every external method?
Yes. Or use a custom marshaler as Jonathan Chambers suggested.
> If I have to convert
> it manually is System.Text.Encoding.UTF32 the right module?
Yes.
What you'd basically need to do is:
[DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl)]
internal unsafe static extern IntPtr
PyUnicode_FromUnicode(IntPtr s, int size);
To manually call:
string s = ".NET string";
IntPtr p = Mono.Unix.UnixMarshal.StringToHeap (s,
System.Text.Encoding.UTF32);
try {
PyUnicode_FromUnicode (p, s.Length);
}
finally {
Mono.Unix.UnixMarshal.FreeHeap (p);
}
This uses the Mono.Unix.UnixMarshal class within Mono.Posix.dll.
For a custom marshaler, your DllImport would be:
[DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl)]
internal unsafe static extern IntPtr
PyUnicode_FromUnicode(
[MarshalAs (UnmanagedType.CustomMarshaler,
MarshalTypeRef=typeof(Utf32Marshaler)]
string path, int size);
with a custom marshaler similar to:
class Utf32Marshaler : ICustomMarshaler {
private static Utf32Marshaler instance = new
Utf32Marshaler ();
public static ICustomMarshaler GetInstance (string s)
{
return instance;
}
public void CleanUpManagedData (object o)
{
}
public void CleanUpNativeData (IntPtr pNativeData)
{
UnixMarshal.FreeHeap (pNativeData);
}
public int GetNativeDataSize ()
{
return IntPtr.Size;
}
public IntPtr MarshalManagedToNative (object obj)
{
string s = obj as string;
if (s == null)
return IntPtr.Zero;
return UnixMarshal.StringToHeap (s,
Encoding.UTF32);
}
public object MarshalNativeToManaged (IntPtr
pNativeData)
{
return UnixMarshal.PtrToString (pNativeData,
Encoding.UTF32);
}
}
This permits easier usage:
string s = ".NET string";
PyUnicode_FromUnicode (s, s.Length);
at the cost of greater runtime overhead to invoke the custom marshaler
(which hopefully won't be too significant, but it depends on how often
it's invoked compared to doing "real work").
- Jon
More information about the Mono-list
mailing list