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

Skip to content

Commit c3f5ee5

Browse files
committed
Fix Py_Main/PySys_SetArgvEx(...) UCS4/PY3 no mem
Based on dmitriyse work.
1 parent d86880a commit c3f5ee5

File tree

2 files changed

+69
-9
lines changed

2 files changed

+69
-9
lines changed

src/embed_tests/pyinitialize.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,6 @@ public static void LoadDefaultArgs()
3333
[Test]
3434
public static void LoadSpecificArgs()
3535
{
36-
if (Environment.GetEnvironmentVariable("TRAVIS") == "true" &&
37-
Environment.GetEnvironmentVariable("TRAVIS_PYTHON_VERSION") != "2.7")
38-
{
39-
Assert.Ignore("FIXME: Fails on Travis/PY3+: Fatal Python error: no mem for sys.argv");
40-
}
4136
var args = new[] { "test1", "test2" };
4237
using (new PythonEngine(args))
4338
using (var argv = new PyList(Runtime.Runtime.PySys_GetObject("argv")))

src/runtime/runtime.cs

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -664,8 +664,41 @@ internal unsafe static extern IntPtr
664664
#if PYTHON3
665665
[DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl,
666666
ExactSpelling = true, CharSet = CharSet.Ansi)]
667-
public unsafe static extern int
668-
Py_Main(int argc, [MarshalAsAttribute(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] string[] argv);
667+
private unsafe static extern int
668+
Py_Main(int argc, [MarshalAsAttribute(UnmanagedType.SysUInt)] IntPtr lplpargv);
669+
670+
public static int Py_Main(int argc, string[] argv)
671+
{
672+
// Totally ignoring argc.
673+
argc = argv.Length;
674+
675+
var allStringsLength = 0;
676+
foreach (string x in argv)
677+
{
678+
allStringsLength += x.Length + 1;
679+
}
680+
int requiredSize = IntPtr.Size * argc + allStringsLength * UCS;
681+
IntPtr mem = Marshal.AllocHGlobal(requiredSize);
682+
try
683+
{
684+
// Preparing array of pointers to UTF32 strings.
685+
IntPtr curStrPtr = mem + argc * IntPtr.Size;
686+
for (var i = 0; i < argv.Length; i++)
687+
{
688+
// Unicode or UTF8 work
689+
Encoding enc = UCS == 2 ? Encoding.Unicode : Encoding.UTF32;
690+
byte[] zstr = enc.GetBytes(argv[i] + "\0");
691+
Marshal.Copy(zstr, 0, curStrPtr, zstr.Length);
692+
Marshal.WriteIntPtr(mem + IntPtr.Size * i, curStrPtr);
693+
curStrPtr += zstr.Length;
694+
}
695+
return Py_Main(argc, mem);
696+
}
697+
finally
698+
{
699+
Marshal.FreeHGlobal(mem);
700+
}
701+
}
669702
#elif PYTHON2
670703
[DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl,
671704
ExactSpelling = true, CharSet = CharSet.Ansi)]
@@ -2078,12 +2111,44 @@ internal unsafe static extern IntPtr
20782111
#if PYTHON3
20792112
[DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl,
20802113
ExactSpelling = true, CharSet = CharSet.Ansi)]
2081-
internal unsafe static extern void
2114+
private unsafe static extern void
20822115
PySys_SetArgvEx(
20832116
int argc,
2084-
[MarshalAsAttribute(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] string[] argv,
2117+
[MarshalAsAttribute(UnmanagedType.SysUInt)] IntPtr lplpargv,
20852118
int updatepath
20862119
);
2120+
2121+
internal static void PySys_SetArgvEx(int argc, string[] argv, int updatepath)
2122+
{
2123+
// Totally ignoring argc.
2124+
argc = argv.Length;
2125+
2126+
var allStringsLength = 0;
2127+
foreach (string x in argv)
2128+
{
2129+
allStringsLength += x.Length + 1;
2130+
}
2131+
int requiredSize = IntPtr.Size * argc + allStringsLength * UCS;
2132+
IntPtr mem = Marshal.AllocHGlobal(requiredSize);
2133+
try
2134+
{
2135+
// Preparing array of pointers to UTF32 strings.
2136+
IntPtr curStrPtr = mem + argc * IntPtr.Size;
2137+
for (var i = 0; i < argv.Length; i++)
2138+
{
2139+
Encoding enc = UCS == 2 ? Encoding.Unicode : Encoding.UTF32;
2140+
byte[] zstr = enc.GetBytes(argv[i] + "\0");
2141+
Marshal.Copy(zstr, 0, curStrPtr, zstr.Length);
2142+
Marshal.WriteIntPtr(mem + IntPtr.Size * i, curStrPtr);
2143+
curStrPtr += zstr.Length;
2144+
}
2145+
PySys_SetArgvEx(argc, mem, updatepath);
2146+
}
2147+
finally
2148+
{
2149+
Marshal.FreeHGlobal(mem);
2150+
}
2151+
}
20872152
#elif PYTHON2
20882153
[DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl,
20892154
ExactSpelling = true, CharSet = CharSet.Ansi)]

0 commit comments

Comments
 (0)