| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 7dba617 commit 6667669
4 files changed
| Original file line number | Diff line number | Diff 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 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -89,6 +89,7 @@ | |||
| 89 | 89 | <Compile Include="constructorbinder.cs" /> | |
| 90 | 90 | <Compile Include="constructorbinding.cs" /> | |
| 91 | 91 | <Compile Include="converter.cs" /> | |
| 92 | + <Compile Include="CustomMarshaler.cs" /> | ||
| 92 | 93 | <Compile Include="debughelper.cs" /> | |
| 93 | 94 | <Compile Include="delegatemanager.cs" /> | |
| 94 | 95 | <Compile Include="delegateobject.cs" /> | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -115,5 +115,27 @@ internal static void debug(string msg) | |||
| 115 | 115 | Console.WriteLine("thread {0} : {1}", tid, caller); | |
| 116 | 116 | Console.WriteLine(" {0}", msg); | |
| 117 | 117 | } | |
| 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 | + } | ||
| 118 | 140 | } | |
| 119 | 141 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1688,34 +1688,10 @@ internal unsafe static extern IntPtr | |||
| 1688 | 1688 | internal unsafe static extern IntPtr | |
| 1689 | 1689 | PyUnicode_FromKindAndString( | |
| 1690 | 1690 | int kind, | |
| 1691 | - IntPtr s, | ||
| 1691 | + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrMarshaler))] string s, | ||
| 1692 | 1692 | int size | |
| 1693 | 1693 | ); | |
| 1694 | 1694 | ||
| 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 | - | ||
| 1719 | 1695 | internal static IntPtr PyUnicode_FromUnicode(string s, int size) | |
| 1720 | 1696 | { | |
| 1721 | 1697 | return PyUnicode_FromKindAndString(4, s, size); | |
@@ -1758,28 +1734,10 @@ internal unsafe static extern IntPtr | |||
| 1758 | 1734 | EntryPoint = "PyUnicodeUCS4_FromUnicode", | |
| 1759 | 1735 | ExactSpelling = true)] | |
| 1760 | 1736 | 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 | + ); | ||
| 1783 | 1741 | ||
| 1784 | 1742 | [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, | |
| 1785 | 1743 | EntryPoint = "PyUnicodeUCS4_GetSize", | |
| Back | FazBrowse Home | New Git URL |
0 commit comments