Skip to content

Commit 790767c

Browse files
vmuriartyagweb
authored andcommitted
Fix get PYTHONHOME/PYTHONPATH marshal
Unlike pythonnet#413, the return type changes between PY2/PY3. Extended Custom Marshaler to convert IntPtr to Unicode String
1 parent 759111a commit 790767c

File tree

3 files changed

+51
-27
lines changed

3 files changed

+51
-27
lines changed

src/runtime/CustomMarshaler.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,33 @@ public static ICustomMarshaler GetInstance(string cookie)
7272
{
7373
return Instance;
7474
}
75+
76+
public static string PtrToStringUni(IntPtr p)
77+
{
78+
if (p == IntPtr.Zero)
79+
{
80+
return null;
81+
}
82+
83+
int size = GetUnicodeByteLength(p);
84+
var buffer = new byte[size];
85+
Marshal.Copy(p, buffer, 0, size);
86+
return PyEncoding.GetString(buffer, 0, size);
87+
}
88+
89+
public static int GetUnicodeByteLength(IntPtr p)
90+
{
91+
var len = 0;
92+
while (true)
93+
{
94+
int c = Runtime.UCS == 2
95+
? Marshal.ReadInt16(p, len * 2)
96+
: Marshal.ReadInt32(p, len * 4);
97+
98+
if (c == 0) return len* Runtime.UCS;
99+
checked{ ++len; }
100+
}
101+
}
75102
}
76103

77104

src/runtime/pythonengine.cs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ public static string ProgramName
5757
{
5858
get
5959
{
60-
string result = Runtime.Py_GetProgramName();
61-
if (result == null)
62-
{
63-
return "";
64-
}
65-
return result;
60+
IntPtr p = Runtime.Py_GetProgramName();
61+
string result = Runtime.IsPython3
62+
? StrMarshaler.PtrToStringUni(p)
63+
: Marshal.PtrToStringAnsi(p);
64+
65+
return result ?? "";
6666
}
6767
set { Runtime.Py_SetProgramName(value); }
6868
}
@@ -71,12 +71,12 @@ public static string PythonHome
7171
{
7272
get
7373
{
74-
string result = Runtime.Py_GetPythonHome();
75-
if (result == null)
76-
{
77-
return "";
78-
}
79-
return result;
74+
IntPtr p = Runtime.Py_GetPythonHome();
75+
string result = Runtime.IsPython3
76+
? StrMarshaler.PtrToStringUni(p)
77+
: Marshal.PtrToStringAnsi(p);
78+
79+
return result ?? "";
8080
}
8181
set { Runtime.Py_SetPythonHome(value); }
8282
}
@@ -85,12 +85,12 @@ public static string PythonPath
8585
{
8686
get
8787
{
88-
string result = Runtime.Py_GetPath();
89-
if (result == null)
90-
{
91-
return "";
92-
}
93-
return result;
88+
IntPtr p = Runtime.Py_GetPath();
89+
string result = Runtime.IsPython3
90+
? StrMarshaler.PtrToStringUni(p)
91+
: Marshal.PtrToStringAnsi(p);
92+
93+
return result ?? "";
9494
}
9595
set { Runtime.Py_SetPath(value); }
9696
}

src/runtime/runtime.cs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -683,46 +683,43 @@ public static extern int Py_Main(
683683

684684
#if PYTHON3
685685
[DllImport(PythonDll)]
686-
[return: MarshalAs(UnmanagedType.LPWStr)]
687-
internal static extern string Py_GetProgramName();
686+
internal static extern IntPtr Py_GetProgramName();
688687

689688
[DllImport(PythonDll)]
690689
internal static extern void Py_SetProgramName(
691690
[MarshalAs(UnmanagedType.LPWStr)] string name
692691
);
693692

694693
[DllImport(PythonDll)]
695-
[return: MarshalAs(UnmanagedType.LPWStr)]
696-
internal static extern string Py_GetPythonHome();
694+
internal static extern IntPtr Py_GetPythonHome();
697695

698696
[DllImport(PythonDll)]
699697
internal static extern void Py_SetPythonHome(
700698
[MarshalAs(UnmanagedType.LPWStr)] string home
701699
);
702700

703701
[DllImport(PythonDll)]
704-
[return: MarshalAs(UnmanagedType.LPWStr)]
705-
internal static extern string Py_GetPath();
702+
internal static extern IntPtr Py_GetPath();
706703

707704
[DllImport(PythonDll)]
708705
internal static extern void Py_SetPath(
709706
[MarshalAs(UnmanagedType.LPWStr)] string home
710707
);
711708
#elif PYTHON2
712709
[DllImport(PythonDll)]
713-
internal static extern string Py_GetProgramName();
710+
internal static extern IntPtr Py_GetProgramName();
714711

715712
[DllImport(PythonDll)]
716713
internal static extern void Py_SetProgramName(string name);
717714

718715
[DllImport(PythonDll)]
719-
internal static extern string Py_GetPythonHome();
716+
internal static extern IntPtr Py_GetPythonHome();
720717

721718
[DllImport(PythonDll)]
722719
internal static extern void Py_SetPythonHome(string home);
723720

724721
[DllImport(PythonDll)]
725-
internal static extern string Py_GetPath();
722+
internal static extern IntPtr Py_GetPath();
726723

727724
[DllImport(PythonDll)]
728725
internal static extern void Py_SetPath(string home);

0 commit comments

Comments
 (0)