| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,22 +2,40 @@ | |||
| 2 | 2 | Legacy Python.NET loader for backwards compatibility | |
| 3 | 3 | """ | |
| 4 | 4 | ||
| 5 | - def _load(): | ||
| 5 | + def _get_netfx_path(): | ||
| 6 | 6 | import os, sys | |
| 7 | - import importlib.util as util | ||
| 8 | 7 | ||
| 9 | 8 | if sys.maxsize > 2 ** 32: | |
| 10 | 9 | arch = "amd64" | |
| 11 | 10 | else: | |
| 12 | 11 | arch = "x86" | |
| 13 | 12 | ||
| 14 | - path = os.path.join(os.path.dirname(__file__), "pythonnet", "dlls", arch, "clr.pyd") | ||
| 15 | - del sys.modules["clr"] | ||
| 13 | + return os.path.join(os.path.dirname(__file__), "pythonnet", "netfx", arch, "clr.pyd") | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + def _get_mono_path(): | ||
| 17 | + import os, glob | ||
| 18 | + | ||
| 19 | + paths = glob.glob(os.path.join(os.path.dirname(__file__), "pythonnet", "mono", "clr.*so")) | ||
| 20 | + return paths[0] | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + def _load_clr(): | ||
| 24 | + import sys | ||
| 25 | + from importlib import util | ||
| 26 | + | ||
| 27 | + if sys.platform == "win32": | ||
| 28 | + path = _get_netfx_path() | ||
| 29 | + else: | ||
| 30 | + path = _get_mono_path() | ||
| 31 | + | ||
| 32 | + del sys.modules[__name__] | ||
| 16 | 33 | ||
| 17 | 34 | spec = util.spec_from_file_location("clr", path) | |
| 18 | 35 | clr = util.module_from_spec(spec) | |
| 19 | 36 | spec.loader.exec_module(clr) | |
| 20 | 37 | ||
| 21 | - sys.modules["clr"] = clr | ||
| 38 | + sys.modules[__name__] = clr | ||
| 39 | + | ||
| 22 | 40 | ||
| 23 | - _load() | ||
| 41 | + _load_clr() | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,3 @@ | |||
| 1 | + mono/ | ||
| 2 | + netfx/ | ||
| 3 | + runtime/ | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,3 @@ | |||
| 1 | + def get_assembly_path(): | ||
| 2 | + import os | ||
| 3 | + return os.path.dirname(__file__) + "/runtime/Python.Runtime.dll" | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,6 +1,6 @@ | |||
| 1 | 1 | #!/usr/bin/env python | |
| 2 | 2 | ||
| 3 | - from setuptools import setup, find_packages, Command, Extension | ||
| 3 | + from setuptools import setup, Command, Extension | ||
| 4 | 4 | from wheel.bdist_wheel import bdist_wheel | |
| 5 | 5 | from setuptools.command.build_ext import build_ext | |
| 6 | 6 | import distutils | |
@@ -164,18 +164,23 @@ def finalize_options(self): | |||
| 164 | 164 | ||
| 165 | 165 | ||
| 166 | 166 | ext_modules = [ | |
| 167 | + DotnetLib( | ||
| 168 | + "python-runtime", | ||
| 169 | + "src/runtime/Python.Runtime.csproj", | ||
| 170 | + output="pythonnet/runtime" | ||
| 171 | + ), | ||
| 167 | 172 | DotnetLib( | |
| 168 | 173 | "clrmodule-amd64", | |
| 169 | 174 | "src/clrmodule/", | |
| 170 | 175 | runtime="win-x64", | |
| 171 | - output="pythonnet/dlls/amd64", | ||
| 176 | + output="pythonnet/netfx/amd64", | ||
| 172 | 177 | rename={"clr.dll": "clr.pyd"}, | |
| 173 | 178 | ), | |
| 174 | 179 | DotnetLib( | |
| 175 | 180 | "clrmodule-x86", | |
| 176 | 181 | "src/clrmodule/", | |
| 177 | 182 | runtime="win-x86", | |
| 178 | - output="pythonnet/dlls/x86", | ||
| 183 | + output="pythonnet/netfx/x86", | ||
| 179 | 184 | rename={"clr.dll": "clr.pyd"}, | |
| 180 | 185 | ), | |
| 181 | 186 | ] | |
@@ -192,7 +197,7 @@ def finalize_options(self): | |||
| 192 | 197 | clr_ext = Extension( | |
| 193 | 198 | "clr", | |
| 194 | 199 | language="c++", | |
| 195 | - sources=["src/monoclr/pynetinit.c", "src/monoclr/clrmod.c"], | ||
| 200 | + sources=["src/monoclr/clrmod.c"], | ||
| 196 | 201 | extra_compile_args=cflags.split(" "), | |
| 197 | 202 | extra_link_args=libs.split(" "), | |
| 198 | 203 | ) | |
@@ -209,6 +214,7 @@ def finalize_options(self): | |||
| 209 | 214 | license="MIT", | |
| 210 | 215 | author="The Contributors of the Python.NET Project", | |
| 211 | 216 | author_email="pythonnet@python.org", | |
| 217 | + packages=["pythonnet"], | ||
| 212 | 218 | setup_requires=["setuptools_scm"], | |
| 213 | 219 | install_requires=["pycparser"], | |
| 214 | 220 | long_description=long_description, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,70 +1,223 @@ | |||
| 1 | - #include "pynetclr.h" | ||
| 1 | + // #define Py_LIMITED_API 0x03050000 | ||
| 2 | + #include <Python.h> | ||
| 2 | 3 | ||
| 3 | - /* List of functions defined in the module */ | ||
| 4 | - static PyMethodDef clr_methods[] = { | ||
| 5 | - {NULL, NULL, 0, NULL} /* Sentinel */ | ||
| 6 | - }; | ||
| 4 | + #include "stdlib.h" | ||
| 7 | 5 | ||
| 8 | - PyDoc_STRVAR(clr_module_doc, | ||
| 9 | - "clr facade module to initialize the CLR. It's later " | ||
| 10 | - "replaced by the real clr module. This module has a facade " | ||
| 11 | - "attribute to make it distinguishable from the real clr module." | ||
| 12 | - ); | ||
| 6 | + #define MONO_VERSION "v4.0.30319.1" | ||
| 7 | + #define MONO_DOMAIN "Python" | ||
| 13 | 8 | ||
| 14 | - static PyNet_Args *pn_args; | ||
| 15 | - char **environ = NULL; | ||
| 16 | - | ||
| 17 | - #if PY_MAJOR_VERSION >= 3 | ||
| 18 | - static struct PyModuleDef clrdef = { | ||
| 19 | - PyModuleDef_HEAD_INIT, | ||
| 20 | - "clr", /* m_name */ | ||
| 21 | - clr_module_doc, /* m_doc */ | ||
| 22 | - -1, /* m_size */ | ||
| 23 | - clr_methods, /* m_methods */ | ||
| 24 | - NULL, /* m_reload */ | ||
| 25 | - NULL, /* m_traverse */ | ||
| 26 | - NULL, /* m_clear */ | ||
| 27 | - NULL, /* m_free */ | ||
| 28 | - }; | ||
| 9 | + #include <mono/jit/jit.h> | ||
| 10 | + #include <mono/metadata/environment.h> | ||
| 11 | + #include <mono/metadata/mono-config.h> | ||
| 12 | + #include <mono/metadata/debug-helpers.h> | ||
| 13 | + #include <mono/metadata/assembly.h> | ||
| 14 | + | ||
| 15 | + #ifndef _WIN32 | ||
| 16 | + #include "dirent.h" | ||
| 17 | + #include "dlfcn.h" | ||
| 18 | + #include "libgen.h" | ||
| 19 | + #include "alloca.h" | ||
| 29 | 20 | #endif | |
| 30 | 21 | ||
| 31 | - static PyObject *_initclr() | ||
| 22 | + typedef struct | ||
| 32 | 23 | { | |
| 33 | - PyObject *m; | ||
| 24 | + MonoDomain *domain; | ||
| 25 | + MonoAssembly *pr_assm; | ||
| 26 | + MonoMethod *shutdown; | ||
| 27 | + const char *pr_file; | ||
| 28 | + char *error; | ||
| 29 | + char *init_name; | ||
| 30 | + char *shutdown_name; | ||
| 31 | + PyObject *module; | ||
| 32 | + } PyNet_Args; | ||
| 34 | 33 | ||
| 35 | - /* Create the module and add the functions */ | ||
| 36 | - #if PY_MAJOR_VERSION >= 3 | ||
| 37 | - m = PyModule_Create(&clrdef); | ||
| 38 | - #else | ||
| 39 | - m = Py_InitModule3("clr", clr_methods, clr_module_doc); | ||
| 40 | - #endif | ||
| 41 | - if (m == NULL) | ||
| 42 | - return NULL; | ||
| 43 | - PyModule_AddObject(m, "facade", Py_True); | ||
| 44 | - Py_INCREF(Py_True); | ||
| 34 | + PyNet_Args *PyNet_Init(void); | ||
| 35 | + static PyNet_Args *pn_args; | ||
| 45 | 36 | ||
| 46 | - pn_args = PyNet_Init(1); | ||
| 37 | + PyMODINIT_FUNC | ||
| 38 | + PyInit_clr(void) | ||
| 39 | + { | ||
| 40 | + pn_args = PyNet_Init(); | ||
| 47 | 41 | if (pn_args->error) | |
| 48 | 42 | { | |
| 49 | 43 | return NULL; | |
| 50 | 44 | } | |
| 51 | 45 | ||
| 52 | - if (NULL != pn_args->module) | ||
| 53 | - return pn_args->module; | ||
| 46 | + return pn_args->module; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + void PyNet_Finalize(PyNet_Args *); | ||
| 50 | + void main_thread_handler(PyNet_Args *user_data); | ||
| 51 | + | ||
| 52 | + // initialize Mono and PythonNet | ||
| 53 | + PyNet_Args *PyNet_Init() | ||
| 54 | + { | ||
| 55 | + PyObject *pn_module; | ||
| 56 | + PyObject *pn_path; | ||
| 57 | + PyNet_Args *pn_args; | ||
| 58 | + pn_args = (PyNet_Args *)malloc(sizeof(PyNet_Args)); | ||
| 59 | + | ||
| 60 | + pn_module = PyImport_ImportModule("pythonnet"); | ||
| 61 | + if (pn_module == NULL) | ||
| 62 | + { | ||
| 63 | + pn_args->error = "Failed to import pythonnet"; | ||
| 64 | + return pn_args; | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + pn_path = PyObject_CallMethod(pn_module, "get_assembly_path", NULL); | ||
| 68 | + if (pn_path == NULL) | ||
| 69 | + { | ||
| 70 | + Py_DecRef(pn_module); | ||
| 71 | + pn_args->error = "Failed to get assembly path"; | ||
| 72 | + return pn_args; | ||
| 73 | + } | ||
| 54 | 74 | ||
| 55 | - return m; | ||
| 75 | + pn_args->pr_file = PyUnicode_AsUTF8(pn_path); | ||
| 76 | + pn_args->error = NULL; | ||
| 77 | + pn_args->shutdown = NULL; | ||
| 78 | + pn_args->module = NULL; | ||
| 79 | + | ||
| 80 | + #ifdef __linux__ | ||
| 81 | + // Force preload libmono-2.0 as global. Without this, on some systems | ||
| 82 | + // symbols from libmono are not found by libmononative (which implements | ||
| 83 | + // some of the System.* namespaces). Since the only happened on Linux so | ||
| 84 | + // far, we hardcode the library name, load the symbols into the global | ||
| 85 | + // namespace and leak the handle. | ||
| 86 | + dlopen("libmono-2.0.so", RTLD_LAZY | RTLD_GLOBAL); | ||
| 87 | + #endif | ||
| 88 | + | ||
| 89 | + pn_args->init_name = "Python.Runtime:InitExt()"; | ||
| 90 | + pn_args->shutdown_name = "Python.Runtime:Shutdown()"; | ||
| 91 | + | ||
| 92 | + pn_args->domain = mono_jit_init_version(MONO_DOMAIN, MONO_VERSION); | ||
| 93 | + | ||
| 94 | + // XXX: Skip setting config for now, should be derived from pr_file | ||
| 95 | + // mono_domain_set_config(pn_args->domain, ".", "Python.Runtime.dll.config"); | ||
| 96 | + | ||
| 97 | + /* | ||
| 98 | + * Load the default Mono configuration file, this is needed | ||
| 99 | + * if you are planning on using the dllmaps defined on the | ||
| 100 | + * system configuration | ||
| 101 | + */ | ||
| 102 | + mono_config_parse(NULL); | ||
| 103 | + | ||
| 104 | + /* I can't use this call to run the main_thread_handler. The function | ||
| 105 | + * runs it in another thread but *this* thread holds the Python | ||
| 106 | + * import lock -> DEAD LOCK. | ||
| 107 | + * | ||
| 108 | + * mono_runtime_exec_managed_code(pn_args->domain, main_thread_handler, | ||
| 109 | + * pn_args); | ||
| 110 | + */ | ||
| 111 | + | ||
| 112 | + main_thread_handler(pn_args); | ||
| 113 | + | ||
| 114 | + if (pn_args->error != NULL) | ||
| 115 | + { | ||
| 116 | + PyErr_SetString(PyExc_ImportError, pn_args->error); | ||
| 117 | + } | ||
| 118 | + return pn_args; | ||
| 56 | 119 | } | |
| 57 | 120 | ||
| 58 | - #if PY_MAJOR_VERSION >= 3 | ||
| 59 | - PyMODINIT_FUNC | ||
| 60 | - PyInit_clr(void) | ||
| 121 | + char *PyNet_ExceptionToString(MonoObject *e); | ||
| 122 | + | ||
| 123 | + // Shuts down PythonNet and cleans up Mono | ||
| 124 | + void PyNet_Finalize(PyNet_Args *pn_args) | ||
| 61 | 125 | { | |
| 62 | - return _initclr(); | ||
| 126 | + MonoObject *exception = NULL; | ||
| 127 | + | ||
| 128 | + if (pn_args->shutdown) | ||
| 129 | + { | ||
| 130 | + mono_runtime_invoke(pn_args->shutdown, NULL, NULL, &exception); | ||
| 131 | + if (exception) | ||
| 132 | + { | ||
| 133 | + pn_args->error = PyNet_ExceptionToString(exception); | ||
| 134 | + } | ||
| 135 | + pn_args->shutdown = NULL; | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + if (pn_args->domain) | ||
| 139 | + { | ||
| 140 | + mono_jit_cleanup(pn_args->domain); | ||
| 141 | + pn_args->domain = NULL; | ||
| 142 | + } | ||
| 143 | + free(pn_args); | ||
| 63 | 144 | } | |
| 64 | - #else | ||
| 65 | - PyMODINIT_FUNC | ||
| 66 | - initclr(void) | ||
| 145 | + | ||
| 146 | + MonoMethod *getMethodFromClass(MonoClass *cls, char *name) | ||
| 67 | 147 | { | |
| 68 | - _initclr(); | ||
| 148 | + MonoMethodDesc *mdesc; | ||
| 149 | + MonoMethod *method; | ||
| 150 | + | ||
| 151 | + mdesc = mono_method_desc_new(name, 1); | ||
| 152 | + method = mono_method_desc_search_in_class(mdesc, cls); | ||
| 153 | + mono_method_desc_free(mdesc); | ||
| 154 | + | ||
| 155 | + return method; | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + void main_thread_handler(PyNet_Args *user_data) | ||
| 159 | + { | ||
| 160 | + PyNet_Args *pn_args = user_data; | ||
| 161 | + MonoMethod *init; | ||
| 162 | + MonoImage *pr_image; | ||
| 163 | + MonoClass *pythonengine; | ||
| 164 | + MonoObject *exception = NULL; | ||
| 165 | + MonoObject *init_result; | ||
| 166 | + | ||
| 167 | + pn_args->pr_assm = mono_domain_assembly_open(pn_args->domain, pn_args->pr_file); | ||
| 168 | + if (!pn_args->pr_assm) | ||
| 169 | + { | ||
| 170 | + pn_args->error = "Unable to load assembly"; | ||
| 171 | + return; | ||
| 172 | + } | ||
| 173 | + | ||
| 174 | + pr_image = mono_assembly_get_image(pn_args->pr_assm); | ||
| 175 | + if (!pr_image) | ||
| 176 | + { | ||
| 177 | + pn_args->error = "Unable to get image"; | ||
| 178 | + return; | ||
| 179 | + } | ||
| 180 | + | ||
| 181 | + pythonengine = mono_class_from_name(pr_image, "Python.Runtime", "PythonEngine"); | ||
| 182 | + if (!pythonengine) | ||
| 183 | + { | ||
| 184 | + pn_args->error = "Unable to load class PythonEngine from Python.Runtime"; | ||
| 185 | + return; | ||
| 186 | + } | ||
| 187 | + | ||
| 188 | + init = getMethodFromClass(pythonengine, pn_args->init_name); | ||
| 189 | + if (!init) | ||
| 190 | + { | ||
| 191 | + pn_args->error = "Unable to fetch Init method from PythonEngine"; | ||
| 192 | + return; | ||
| 193 | + } | ||
| 194 | + | ||
| 195 | + pn_args->shutdown = getMethodFromClass(pythonengine, pn_args->shutdown_name); | ||
| 196 | + if (!pn_args->shutdown) | ||
| 197 | + { | ||
| 198 | + pn_args->error = "Unable to fetch shutdown method from PythonEngine"; | ||
| 199 | + return; | ||
| 200 | + } | ||
| 201 | + | ||
| 202 | + init_result = mono_runtime_invoke(init, NULL, NULL, &exception); | ||
| 203 | + if (exception) | ||
| 204 | + { | ||
| 205 | + pn_args->error = PyNet_ExceptionToString(exception); | ||
| 206 | + return; | ||
| 207 | + } | ||
| 208 | + | ||
| 209 | + pn_args->module = *(PyObject**)mono_object_unbox(init_result); | ||
| 210 | + } | ||
| 211 | + | ||
| 212 | + // Get string from a Mono exception | ||
| 213 | + char *PyNet_ExceptionToString(MonoObject *e) | ||
| 214 | + { | ||
| 215 | + MonoMethodDesc *mdesc = mono_method_desc_new(":ToString()", 0 /*FALSE*/); | ||
| 216 | + MonoMethod *mmethod = mono_method_desc_search_in_class(mdesc, mono_get_object_class()); | ||
| 217 | + mono_method_desc_free(mdesc); | ||
| 218 | + | ||
| 219 | + mmethod = mono_object_get_virtual_method(e, mmethod); | ||
| 220 | + MonoString *monoString = (MonoString*) mono_runtime_invoke(mmethod, e, NULL, NULL); | ||
| 221 | + mono_runtime_invoke(mmethod, e, NULL, NULL); | ||
| 222 | + return mono_string_to_utf8(monoString); | ||
| 69 | 223 | } | |
| 70 | - #endif | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments