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

Skip to content

Commit d01f25f

Browse files
committed
Add ICustomMarshaler StrArrayMarshaler
1 parent 6667669 commit d01f25f

File tree

2 files changed

+56
-67
lines changed

2 files changed

+56
-67
lines changed

src/runtime/CustomMarshaler.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,58 @@ public static ICustomMarshaler GetInstance(string cookie)
7777
return Instance;
7878
}
7979
}
80+
81+
82+
/// <summary>
83+
/// Custom Marshaler to deal with Managed String Arrays to Native
84+
/// conversion differences on UCS2/UCS4.
85+
/// </summary>
86+
public class StrArrayMarshaler : MarshalerBase
87+
{
88+
private static readonly MarshalerBase Instance = new StrArrayMarshaler();
89+
90+
public override IntPtr MarshalManagedToNative(object managedObj)
91+
{
92+
var argv = managedObj as string[];
93+
94+
if (argv == null)
95+
{
96+
return IntPtr.Zero;
97+
}
98+
99+
var totalStrLength = 0;
100+
foreach (string arg in argv)
101+
{
102+
totalStrLength += arg.Length + 1;
103+
}
104+
int memSize = argv.Length * IntPtr.Size + totalStrLength * Runtime.UCS;
105+
106+
IntPtr mem = Marshal.AllocHGlobal(memSize);
107+
try
108+
{
109+
// Preparing array of pointers to strings
110+
IntPtr curStrPtr = mem + argv.Length * IntPtr.Size;
111+
for (var i = 0; i < argv.Length; i++)
112+
{
113+
Encoding encoding = Runtime.UCS == 2 ? Encoding.Unicode : Encoding.UTF32;
114+
byte[] bStr = encoding.GetBytes(argv[i] + "\0");
115+
Marshal.Copy(bStr, 0, curStrPtr, bStr.Length);
116+
Marshal.WriteIntPtr(mem + i * IntPtr.Size, curStrPtr);
117+
curStrPtr += bStr.Length;
118+
}
119+
}
120+
catch (Exception)
121+
{
122+
Marshal.FreeHGlobal(mem);
123+
throw;
124+
}
125+
126+
return mem;
127+
}
128+
129+
public static ICustomMarshaler GetInstance(string cookie)
130+
{
131+
return Instance;
132+
}
133+
}
80134
}

src/runtime/runtime.cs

Lines changed: 2 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -667,41 +667,8 @@ internal unsafe static extern IntPtr
667667
public unsafe static extern int
668668
Py_Main(
669669
int argc,
670-
IntPtr lplpargv
670+
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv
671671
);
672-
673-
public static int Py_Main(int argc, string[] argv)
674-
{
675-
// Totally ignoring argc.
676-
argc = argv.Length;
677-
678-
var allStringsLength = 0;
679-
foreach (string x in argv)
680-
{
681-
allStringsLength += x.Length + 1;
682-
}
683-
int requiredSize = IntPtr.Size * argc + allStringsLength * UCS;
684-
IntPtr mem = Marshal.AllocHGlobal(requiredSize);
685-
try
686-
{
687-
// Preparing array of pointers to UTF32 strings.
688-
IntPtr curStrPtr = mem + argc * IntPtr.Size;
689-
for (var i = 0; i < argv.Length; i++)
690-
{
691-
// Unicode or UTF8 work
692-
Encoding enc = UCS == 2 ? Encoding.Unicode : Encoding.UTF32;
693-
byte[] zstr = enc.GetBytes(argv[i] + "\0");
694-
Marshal.Copy(zstr, 0, curStrPtr, zstr.Length);
695-
Marshal.WriteIntPtr(mem + IntPtr.Size * i, curStrPtr);
696-
curStrPtr += zstr.Length;
697-
}
698-
return Py_Main(argc, mem);
699-
}
700-
finally
701-
{
702-
Marshal.FreeHGlobal(mem);
703-
}
704-
}
705672
#elif PYTHON2
706673
[DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl,
707674
ExactSpelling = true, CharSet = CharSet.Ansi)]
@@ -2078,41 +2045,9 @@ internal unsafe static extern IntPtr
20782045
internal unsafe static extern void
20792046
PySys_SetArgvEx(
20802047
int argc,
2081-
IntPtr lplpargv,
2048+
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv,
20822049
int updatepath
20832050
);
2084-
2085-
internal static void PySys_SetArgvEx(int argc, string[] argv, int updatepath)
2086-
{
2087-
// Totally ignoring argc.
2088-
argc = argv.Length;
2089-
2090-
var allStringsLength = 0;
2091-
foreach (string x in argv)
2092-
{
2093-
allStringsLength += x.Length + 1;
2094-
}
2095-
int requiredSize = IntPtr.Size * argc + allStringsLength * UCS;
2096-
IntPtr mem = Marshal.AllocHGlobal(requiredSize);
2097-
try
2098-
{
2099-
// Preparing array of pointers to UTF32 strings.
2100-
IntPtr curStrPtr = mem + argc * IntPtr.Size;
2101-
for (var i = 0; i < argv.Length; i++)
2102-
{
2103-
Encoding enc = UCS == 2 ? Encoding.Unicode : Encoding.UTF32;
2104-
byte[] zstr = enc.GetBytes(argv[i] + "\0");
2105-
Marshal.Copy(zstr, 0, curStrPtr, zstr.Length);
2106-
Marshal.WriteIntPtr(mem + IntPtr.Size * i, curStrPtr);
2107-
curStrPtr += zstr.Length;
2108-
}
2109-
PySys_SetArgvEx(argc, mem, updatepath);
2110-
}
2111-
finally
2112-
{
2113-
Marshal.FreeHGlobal(mem);
2114-
}
2115-
}
21162051
#elif PYTHON2
21172052
[DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl,
21182053
ExactSpelling = true, CharSet = CharSet.Ansi)]

0 commit comments

Comments
 (0)