| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,9 +4,6 @@ sphinx | |||
| 4 | 4 | furo>=2022.9.15 | |
| 5 | 5 | pygments>=2.7 | |
| 6 | 6 | ||
| 7 | - # Markdown | ||
| 8 | - myst-parser | ||
| 9 | - | ||
| 10 | 7 | # C# via doxygen | |
| 11 | 8 | breathe | |
| 12 | 9 | git+https://github.com/rogerbarton/sphinx-csharp.git | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,69 @@ | |||
| 1 | + .. _codecs: | ||
| 2 | + | ||
| 3 | + Codecs | ||
| 4 | + ====== | ||
| 5 | + | ||
| 6 | + Python.NET performs some conversions between .NET and Python automatically. | ||
| 7 | + For example, when Python calls this C# method: | ||
| 8 | + | ||
| 9 | + .. code:: csharp | ||
| 10 | + | ||
| 11 | + void Foo(int bar) { ... } | ||
| 12 | + | ||
| 13 | + via ``Foo(42)``, Python value ``42`` of type ``int`` will be | ||
| 14 | + automatically converted to .NET type ``System.Int32``. Another way to | ||
| 15 | + invoke those conversions is to call ``dotNetObject.ToPython()`` | ||
| 16 | + (available as an extension method) or ``pyObject.As<T>()`` to convert | ||
| 17 | + ``PyObject`` to .NET. | ||
| 18 | + | ||
| 19 | + An incomplete list of Python types, that are converted between Python | ||
| 20 | + and .NET automatically: most numeric types, ``bool``, ``string``, | ||
| 21 | + ``Nullable<T>`` to its ``Value`` or ``None`` and back, etc. | ||
| 22 | + | ||
| 23 | + A custom conversion (**Codec**) can be defined by implementing one of the (or | ||
| 24 | + both) interfaces: | ||
| 25 | + | ||
| 26 | + - ``Python.Runtime.IPyObjectDecoder`` to marshal Python objects to .NET | ||
| 27 | + | ||
| 28 | + .. code:: csharp | ||
| 29 | + | ||
| 30 | + interface IPyObjectDecoder { | ||
| 31 | + bool CanDecode(PyObject objectType, System.Type targetType); | ||
| 32 | + bool TryDecode<T>(PyObject pyObj, out T value); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + - ``Python.Runtime.IPyObjectEncoder`` to marshal .NET objects to Python | ||
| 36 | + | ||
| 37 | + .. code:: csharp | ||
| 38 | + | ||
| 39 | + interface IPyObjectEncoder { | ||
| 40 | + bool CanEncode(System.Type); | ||
| 41 | + PyObject TryEncode(System.Object); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + Once implemented, instances have to be registered with | ||
| 45 | + ``Python.Runtime.PyObjectConversions.RegisterEncoder``/``-Decoder``. One | ||
| 46 | + can override *some* of the default conversions by registering new | ||
| 47 | + codecs. | ||
| 48 | + | ||
| 49 | + Codec priorities | ||
| 50 | + ~~~~~~~~~~~~~~~~ | ||
| 51 | + | ||
| 52 | + When multiple codecs are registered, the runtime will first try the ones, that | ||
| 53 | + were registered earlier. If you need to have some grouping of codecs by | ||
| 54 | + priority, create and expose | ||
| 55 | + ``Python.Runtime.Codecs.EncoderGroup``/``-.DecoderGroup``. For example: | ||
| 56 | + | ||
| 57 | + .. code:: csharp | ||
| 58 | + | ||
| 59 | + public static EncoderGroup HighPriorityEncoders{ get; } = new EncoderGroup(); | ||
| 60 | + | ||
| 61 | + void Init() { | ||
| 62 | + PyObjectConversions.RegisterEncoder(HighPriorityEncoders); | ||
| 63 | + var lowPriorityEncoder = new SomeEncoder(); | ||
| 64 | + PyObjectConversions.RegisterEncoder(lowPriorityEncoder); | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + ... some time later | ||
| 68 | + | ||
| 69 | + HighPriorityEncoders.Add(new SomeOtherEncoder()); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -10,16 +10,15 @@ | |||
| 10 | 10 | # add these directories to sys.path here. If the directory is relative to the | |
| 11 | 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. | |
| 12 | 12 | # | |
| 13 | - # import os | ||
| 14 | - # import sys | ||
| 15 | - # sys.path.insert(0, os.path.abspath('.')) | ||
| 13 | + import os, sys | ||
| 14 | + sys.path.insert(0, os.path.abspath('../..')) | ||
| 16 | 15 | ||
| 17 | 16 | ||
| 18 | 17 | # -- Project information ----------------------------------------------------- | |
| 19 | 18 | ||
| 20 | - project = 'Python.NET' | ||
| 21 | - copyright = '2022, The Python.NET Project Contributors' | ||
| 22 | - author = 'The Python.NET Project Contributors' | ||
| 19 | + project = "Python.NET" | ||
| 20 | + copyright = "2022, The Python.NET Project Contributors" | ||
| 21 | + author = "The Python.NET Project Contributors" | ||
| 23 | 22 | ||
| 24 | 23 | ||
| 25 | 24 | # -- General configuration --------------------------------------------------- | |
@@ -28,14 +27,14 @@ | |||
| 28 | 27 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom | |
| 29 | 28 | # ones. | |
| 30 | 29 | extensions = [ | |
| 31 | - 'myst_parser', | ||
| 32 | - 'breathe', | ||
| 33 | - 'sphinx.ext.autodoc', | ||
| 34 | - 'sphinx_csharp', | ||
| 30 | + "breathe", | ||
| 31 | + "sphinx.ext.autodoc", | ||
| 32 | + "sphinx_csharp", | ||
| 33 | + "sphinx.ext.intersphinx", | ||
| 35 | 34 | ] | |
| 36 | 35 | ||
| 37 | 36 | # Add any paths that contain templates here, relative to this directory. | |
| 38 | - templates_path = ['_templates'] | ||
| 37 | + templates_path = ["_templates"] | ||
| 39 | 38 | ||
| 40 | 39 | # List of patterns, relative to source directory, that match files and | |
| 41 | 40 | # directories to ignore when looking for source files. | |
@@ -48,12 +47,14 @@ | |||
| 48 | 47 | # The theme to use for HTML and HTML Help pages. See the documentation for | |
| 49 | 48 | # a list of builtin themes. | |
| 50 | 49 | # | |
| 51 | - html_theme = 'furo' | ||
| 50 | + html_theme = "furo" | ||
| 52 | 51 | ||
| 53 | 52 | # Add any paths that contain custom static files (such as style sheets) here, | |
| 54 | 53 | # relative to this directory. They are copied after the builtin static files, | |
| 55 | 54 | # so a file named "default.css" will overwrite the builtin "default.css". | |
| 56 | - html_static_path = ['_static'] | ||
| 55 | + html_static_path = ["_static"] | ||
| 57 | 56 | ||
| 58 | - breathe_projects = { "pythonnet": "../doxygen_xml" } | ||
| 59 | - breathe_default_project = 'pythonnet' | ||
| 57 | + breathe_projects = {"pythonnet": "../doxygen_xml"} | ||
| 58 | + breathe_default_project = "pythonnet" | ||
| 59 | + | ||
| 60 | + intersphinx_mapping = {"clr-loader": ("https://pythonnet.github.io/clr-loader/", None)} | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,114 @@ | |||
| 1 | + Embedding Python into .NET | ||
| 2 | + ========================== | ||
| 3 | + | ||
| 4 | + .. warning:: | ||
| 5 | + Because Python code running under Python.NET is inherently | ||
| 6 | + unverifiable, it runs totally under the radar of the security | ||
| 7 | + infrastructure of the CLR so you should restrict use of the Python | ||
| 8 | + assembly to trusted code. | ||
| 9 | + | ||
| 10 | + The Python runtime assembly defines a number of public classes that | ||
| 11 | + provide a subset of the functionality provided by the Python C-API. | ||
| 12 | + | ||
| 13 | + These classes include PyObject, PyList, PyDict, PyTuple, etc. | ||
| 14 | + | ||
| 15 | + At a very high level, to embed Python in your application one will need | ||
| 16 | + to: | ||
| 17 | + | ||
| 18 | + - Reference ``Python.Runtime.dll`` (e.g. via a ``PackageReference``) | ||
| 19 | + - Call ``PythonEngine.Initialize()`` to initialize Python | ||
| 20 | + - Call ``PythonEngine.ImportModule(name)`` to import a module | ||
| 21 | + | ||
| 22 | + The module you import can either start working with your managed app | ||
| 23 | + environment at the time its imported, or you can explicitly lookup and | ||
| 24 | + call objects in a module you import. | ||
| 25 | + | ||
| 26 | + For general-purpose information on embedding Python in applications, use | ||
| 27 | + www.python.org or Google to find (C) examples. Because Python.NET is so | ||
| 28 | + closely integrated with the managed environment, one will generally be | ||
| 29 | + better off importing a module and deferring to Python code as early as | ||
| 30 | + possible rather than writing a lot of managed embedding code. | ||
| 31 | + | ||
| 32 | + .. note:: | ||
| 33 | + Python is not free-threaded and uses a | ||
| 34 | + global interpreter lock to allow multi-threaded applications to interact | ||
| 35 | + safely with the Python interpreter. Much more information about this is | ||
| 36 | + available in the Python C-API documentation on the www.python.org | ||
| 37 | + Website. | ||
| 38 | + | ||
| 39 | + When embedding Python in a managed application, one has to manage the | ||
| 40 | + GIL in just the same way you would when embedding Python in a C or C++ | ||
| 41 | + application. | ||
| 42 | + | ||
| 43 | + Before interacting with any of the objects or APIs provided by the | ||
| 44 | + ``Python.Runtime`` namespace, calling code must have acquired the Python | ||
| 45 | + global interpreter lock by calling the ``PythonEngine.AcquireLock`` | ||
| 46 | + method. The only exception to this rule is the | ||
| 47 | + ``PythonEngine.Initialize`` method, which may be called at startup | ||
| 48 | + without having acquired the GIL. | ||
| 49 | + | ||
| 50 | + When finished using Python APIs, managed code must call a corresponding | ||
| 51 | + ``PythonEngine.ReleaseLock`` to release the GIL and allow other threads | ||
| 52 | + to use Python. | ||
| 53 | + | ||
| 54 | + A ``using`` statement may be used to acquire and release the GIL: | ||
| 55 | + | ||
| 56 | + .. code:: csharp | ||
| 57 | + | ||
| 58 | + using (Py.GIL()) | ||
| 59 | + { | ||
| 60 | + PythonEngine.Exec("doStuff()"); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + The AcquireLock and ReleaseLock methods are thin wrappers over the | ||
| 64 | + unmanaged ``PyGILState_Ensure`` and ``PyGILState_Release`` functions | ||
| 65 | + from the Python API, and the documentation for those APIs applies to the | ||
| 66 | + managed versions. | ||
| 67 | + | ||
| 68 | + Passing C# Objects to the Python Engine | ||
| 69 | + --------------------------------------- | ||
| 70 | + | ||
| 71 | + This section demonstrates how to pass a C# object to the Python runtime. | ||
| 72 | + The example uses the following ``Person`` class: | ||
| 73 | + | ||
| 74 | + .. code:: csharp | ||
| 75 | + | ||
| 76 | + public class Person | ||
| 77 | + { | ||
| 78 | + public Person(string firstName, string lastName) | ||
| 79 | + { | ||
| 80 | + FirstName = firstName; | ||
| 81 | + LastName = lastName; | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + public string FirstName { get; set; } | ||
| 85 | + public string LastName { get; set; } | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + In order to pass a C# object to the Python runtime, it must be converted | ||
| 89 | + to a ``PyObject``. This is done using the ``ToPython()`` extension | ||
| 90 | + method. The ``PyObject`` may then be set as a variable in a ``PyScope``. | ||
| 91 | + Code executed from the scope will have access to the variable: | ||
| 92 | + | ||
| 93 | + .. code:: csharp | ||
| 94 | + | ||
| 95 | + // create a person object | ||
| 96 | + Person person = new Person("John", "Smith"); | ||
| 97 | + | ||
| 98 | + // acquire the GIL before using the Python interpreter | ||
| 99 | + using (Py.GIL()) | ||
| 100 | + { | ||
| 101 | + // create a Python scope | ||
| 102 | + using (PyScope scope = Py.CreateScope()) | ||
| 103 | + { | ||
| 104 | + // convert the Person object to a PyObject | ||
| 105 | + PyObject pyPerson = person.ToPython(); | ||
| 106 | + | ||
| 107 | + // create a Python variable "person" | ||
| 108 | + scope.Set("person", pyPerson); | ||
| 109 | + | ||
| 110 | + // the person object may now be used in Python | ||
| 111 | + string code = "fullName = person.FirstName + ' ' + person.LastName"; | ||
| 112 | + scope.Exec(code); | ||
| 113 | + } | ||
| 114 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments