diff --git a/src/embed_tests/InitializeTest.cs b/src/embed_tests/InitializeTest.cs
index a9667343c..6c6f0f1f1 100644
--- a/src/embed_tests/InitializeTest.cs
+++ b/src/embed_tests/InitializeTest.cs
@@ -10,7 +10,29 @@ namespace Python.EmbeddingTest
public class InitializeTest
{
[Test]
- public static void Test()
+ public static void LoadSpecificArgs()
+ {
+ var args = new[] { "test1", "test2" };
+ using (new PythonEngine(args))
+ using (var argv = new PyList(Runtime.Runtime.PySys_GetObject("argv")))
+ {
+ Assert.That(argv[0].ToString() == args[0]);
+ Assert.That(argv[1].ToString() == args[1]);
+ }
+ }
+
+ [Test]
+ public static void LoadDefaultArgs()
+ {
+ using (new PythonEngine())
+ using (var argv = new PyList(Runtime.Runtime.PySys_GetObject("argv")))
+ {
+ Assert.That(argv.Length() != 0);
+ }
+ }
+
+ [Test]
+ public static void StartAndStopTwice()
{
PythonEngine.Initialize();
PythonEngine.Shutdown();
diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs
index c296f1b87..754aaf2cd 100644
--- a/src/runtime/pythonengine.cs
+++ b/src/runtime/pythonengine.cs
@@ -2,17 +2,39 @@
using System.IO;
using System.Threading;
using System.Reflection;
+using System.Collections.Generic;
+using System.Linq;
namespace Python.Runtime
{
///
/// This class provides the public interface of the Python runtime.
///
- public class PythonEngine
+ public class PythonEngine : IDisposable
{
private static DelegateManager delegateManager;
private static bool initialized;
+ public PythonEngine()
+ {
+ Initialize();
+ }
+
+ public PythonEngine(params string[] args)
+ {
+ Initialize(args);
+ }
+
+ public PythonEngine(IEnumerable args)
+ {
+ Initialize(args);
+ }
+
+ public void Dispose()
+ {
+ Shutdown();
+ }
+
#region Properties
public static bool IsInitialized
@@ -102,6 +124,11 @@ public static int RunSimpleString(string code)
#endregion
+ public static void Initialize()
+ {
+ Initialize(Enumerable.Empty());
+ }
+
///
/// Initialize Method
///
@@ -112,7 +139,7 @@ public static int RunSimpleString(string code)
/// first call. It is *not* necessary to hold the Python global
/// interpreter lock (GIL) to call this method.
///
- public static void Initialize()
+ public static void Initialize(IEnumerable args)
{
if (!initialized)
{
@@ -126,6 +153,8 @@ public static void Initialize()
initialized = true;
Exceptions.Clear();
+ Py.SetArgv(args);
+
// register the atexit callback (this doesn't use Py_AtExit as the C atexit
// callbacks are called after python is fully finalized but the python ones
// are called while the python engine is still running).
@@ -187,7 +216,8 @@ public static void Initialize()
// when it is imported by the CLR extension module.
//====================================================================
#if PYTHON3
- public static IntPtr InitExt() {
+ public static IntPtr InitExt()
+ {
#elif PYTHON2
public static void InitExt()
{
@@ -351,10 +381,7 @@ public static void EndAllowThreads(IntPtr ts)
public static PyObject ImportModule(string name)
{
IntPtr op = Runtime.PyImport_ImportModule(name);
- if (op == IntPtr.Zero)
- {
- return null;
- }
+ Py.Throw();
return new PyObject(op);
}
@@ -370,10 +397,7 @@ public static PyObject ImportModule(string name)
public static PyObject ReloadModule(PyObject module)
{
IntPtr op = Runtime.PyImport_ReloadModule(module.Handle);
- if (op == IntPtr.Zero)
- {
- throw new PythonException();
- }
+ Py.Throw();
return new PyObject(op);
}
@@ -389,15 +413,9 @@ public static PyObject ReloadModule(PyObject module)
public static PyObject ModuleFromString(string name, string code)
{
IntPtr c = Runtime.Py_CompileString(code, "none", (IntPtr)257);
- if (c == IntPtr.Zero)
- {
- throw new PythonException();
- }
+ Py.Throw();
IntPtr m = Runtime.PyImport_ExecCodeModule(name, c);
- if (m == IntPtr.Zero)
- {
- throw new PythonException();
- }
+ Py.Throw();
return new PyObject(m);
}
@@ -445,10 +463,7 @@ public static PyObject RunString(
code, flag, globals.Value, locals.Value
);
- if (Runtime.PyErr_Occurred() != 0)
- {
- throw new PythonException();
- }
+ Py.Throw();
return new PyObject(result);
}
@@ -500,7 +515,7 @@ public class KeywordArguments : PyDict
public static KeywordArguments kw(params object[] kv)
{
var dict = new KeywordArguments();
- if (kv.Length%2 != 0)
+ if (kv.Length % 2 != 0)
throw new ArgumentException("Must have an equal number of keys and values");
for (int i = 0; i < kv.Length; i += 2)
{
@@ -521,5 +536,50 @@ public static PyObject Import(string name)
{
return PythonEngine.ImportModule(name);
}
+
+ public static void SetArgv()
+ {
+ IEnumerable args;
+ try
+ {
+ args = Environment.GetCommandLineArgs();
+ }
+ catch (NotSupportedException)
+ {
+ args = Enumerable.Empty();
+ }
+
+ SetArgv(
+ new[] { "" }.Concat(
+ Environment.GetCommandLineArgs().Skip(1)
+ )
+ );
+ }
+
+ public static void SetArgv(params string[] argv)
+ {
+ SetArgv(argv as IEnumerable);
+ }
+
+ public static void SetArgv(IEnumerable argv)
+ {
+ using (GIL())
+ {
+ var arr = argv.ToArray();
+ Runtime.PySys_SetArgvEx(arr.Length, arr, 0);
+ Py.Throw();
+ }
+ }
+
+ internal static void Throw()
+ {
+ using (GIL())
+ {
+ if (Runtime.PyErr_Occurred() != 0)
+ {
+ throw new PythonException();
+ }
+ }
+ }
}
}
diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs
index 5f0ecfbd2..9b5c4ffb5 100644
--- a/src/runtime/runtime.cs
+++ b/src/runtime/runtime.cs
@@ -2027,11 +2027,26 @@ internal unsafe static extern IntPtr
internal unsafe static extern IntPtr
PyImport_GetModuleDict();
-
+#if PYTHON3
[DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl,
ExactSpelling = true, CharSet = CharSet.Ansi)]
internal unsafe static extern void
- PySys_SetArgv(int argc, IntPtr argv);
+ PySys_SetArgvEx(
+ int argc,
+ [MarshalAsAttribute(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)]
+ string[] argv,
+ int updatepath
+ );
+#elif PYTHON2
+ [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl,
+ ExactSpelling = true, CharSet = CharSet.Ansi)]
+ internal unsafe static extern void
+ PySys_SetArgvEx(
+ int argc,
+ string[] argv,
+ int updatepath
+ );
+#endif
[DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl,
ExactSpelling = true, CharSet = CharSet.Ansi)]