Thanks to visit codestin.com
Credit goes to github.com

Skip to content

File tree

4 files changed

+108
-47
lines changed

4 files changed

+108
-47
lines changed

src/runtime/CustomMarshaler.cs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using System.Text;
4+
5+
namespace Python.Runtime
6+
{
7+
/// <summary>
8+
/// Abstract class defining boiler plate methods that
9+
/// Custom Marshalers will use.
10+
/// </summary>
11+
public abstract class MarshalerBase : ICustomMarshaler
12+
{
13+
public object MarshalNativeToManaged(IntPtr pNativeData)
14+
{
15+
throw new NotImplementedException();
16+
}
17+
18+
public abstract IntPtr MarshalManagedToNative(object managedObj);
19+
20+
public void CleanUpNativeData(IntPtr pNativeData)
21+
{
22+
Marshal.FreeHGlobal(pNativeData);
23+
}
24+
25+
public void CleanUpManagedData(object managedObj)
26+
{
27+
// Let GC deal with it
28+
}
29+
30+
public int GetNativeDataSize()
31+
{
32+
return IntPtr.Size;
33+
}
34+
}
35+
36+
37+
/// <summary>
38+
/// Custom Marshaler to deal with Managed String to Native
39+
/// conversion differences on UCS2/UCS4.
40+
/// </summary>
41+
public class StrMarshaler : MarshalerBase
42+
{
43+
private static readonly MarshalerBase Instance = new StrMarshaler();
44+
45+
public override IntPtr MarshalManagedToNative(object managedObj)
46+
{
47+
Encoding encoding = Runtime.UCS == 2 ? Encoding.Unicode : Encoding.UTF32;
48+
var s = managedObj as string;
49+
50+
if (s == null)
51+
{
52+
return IntPtr.Zero;
53+
}
54+
55+
int minByteCount = encoding.GetMaxByteCount(1);
56+
char[] cStr = s.ToCharArray(0, s.Length);
57+
byte[] bStr = new byte[encoding.GetByteCount(cStr) + minByteCount];
58+
encoding.GetBytes(cStr, 0, cStr.Length, bStr, 0);
59+
DebugUtil.PrintHexBytes(bStr);
60+
61+
IntPtr mem = Marshal.AllocHGlobal(bStr.Length);
62+
try
63+
{
64+
Marshal.Copy(bStr, 0, mem, bStr.Length);
65+
}
66+
catch (Exception)
67+
{
68+
Marshal.FreeHGlobal(mem);
69+
throw;
70+
}
71+
72+
return mem;
73+
}
74+
75+
public static ICustomMarshaler GetInstance(string cookie)
76+
{
77+
return Instance;
78+
}
79+
}
80+
}

src/runtime/Python.Runtime.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
<Compile Include="constructorbinder.cs" />
9090
<Compile Include="constructorbinding.cs" />
9191
<Compile Include="converter.cs" />
92+
<Compile Include="CustomMarshaler.cs" />
9293
<Compile Include="debughelper.cs" />
9394
<Compile Include="delegatemanager.cs" />
9495
<Compile Include="delegateobject.cs" />

src/runtime/debughelper.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,5 +115,27 @@ internal static void debug(string msg)
115115
Console.WriteLine("thread {0} : {1}", tid, caller);
116116
Console.WriteLine(" {0}", msg);
117117
}
118+
119+
/// <summary>
120+
/// Helper function to inspect/compare managed to native conversions.
121+
/// Especially useful when debugging CustomMarshaler.
122+
/// </summary>
123+
/// <param name="bytes"></param>
124+
[Conditional("DEBUG")]
125+
public static void PrintHexBytes(byte[] bytes)
126+
{
127+
if ((bytes == null) || (bytes.Length == 0))
128+
{
129+
Console.WriteLine("<none>");
130+
}
131+
else
132+
{
133+
foreach (byte t in bytes)
134+
{
135+
Console.Write("{0:X2} ", t);
136+
}
137+
Console.WriteLine();
138+
}
139+
}
118140
}
119141
}

src/runtime/runtime.cs

Lines changed: 5 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,34 +1688,10 @@ internal unsafe static extern IntPtr
16881688
internal unsafe static extern IntPtr
16891689
PyUnicode_FromKindAndString(
16901690
int kind,
1691-
IntPtr s,
1691+
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrMarshaler))] string s,
16921692
int size
16931693
);
16941694

1695-
internal static unsafe IntPtr PyUnicode_FromKindAndString(
1696-
int kind,
1697-
string s,
1698-
int size)
1699-
{
1700-
var bufLength = Math.Max(s.Length, size) * 4;
1701-
1702-
IntPtr mem = Marshal.AllocHGlobal(bufLength);
1703-
try
1704-
{
1705-
fixed (char* ps = s)
1706-
{
1707-
Encoding.UTF32.GetBytes(ps, s.Length, (byte*)mem, bufLength);
1708-
}
1709-
1710-
var result = PyUnicode_FromKindAndString(kind, mem, size);
1711-
return result;
1712-
}
1713-
finally
1714-
{
1715-
Marshal.FreeHGlobal(mem);
1716-
}
1717-
}
1718-
17191695
internal static IntPtr PyUnicode_FromUnicode(string s, int size)
17201696
{
17211697
return PyUnicode_FromKindAndString(4, s, size);
@@ -1758,28 +1734,10 @@ internal unsafe static extern IntPtr
17581734
EntryPoint = "PyUnicodeUCS4_FromUnicode",
17591735
ExactSpelling = true)]
17601736
internal unsafe static extern IntPtr
1761-
PyUnicode_FromUnicode(IntPtr s, int size);
1762-
1763-
internal static unsafe IntPtr PyUnicode_FromUnicode(string s, int size)
1764-
{
1765-
var bufLength = Math.Max(s.Length, size) * 4;
1766-
1767-
IntPtr mem = Marshal.AllocHGlobal(bufLength);
1768-
try
1769-
{
1770-
fixed (char* ps = s)
1771-
{
1772-
Encoding.UTF32.GetBytes(ps, s.Length, (byte*)mem, bufLength);
1773-
}
1774-
1775-
var result = PyUnicode_FromUnicode(mem, size);
1776-
return result;
1777-
}
1778-
finally
1779-
{
1780-
Marshal.FreeHGlobal(mem);
1781-
}
1782-
}
1737+
PyUnicode_FromUnicode(
1738+
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrMarshaler))] string s,
1739+
int size
1740+
);
17831741

17841742
[DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl,
17851743
EntryPoint = "PyUnicodeUCS4_GetSize",

0 commit comments

Comments
 (0)