-
Notifications
You must be signed in to change notification settings - Fork 0
Plan
我的主要目标是构建单个发行版,适用于 (理想中) Python 2.7, 和 >3.5 以及 .NET Framework, CoreCLR 和 Mono。
- 将 CLR 加载代码分离到一个单独的库中 (可能使用 CFFI 或直接使用 ctypes 来实现,以简化构建和分发)
- 统一这个 CLR 加载器,这样它至少可以与 Mono 和 CoreCLR 一起工作 (对于 .NET 框架,我们可能仍然依赖于现有的基于UnmanagedExports 的加载器)
新的 clr
模块也许可以使用 pypi 中现有的 clr
名称,该库的作者根据我们的请求将其很好地重命名。它应该提供一个清晰的接口来加载特定的 VM 并在其上提供 “直接互操作”,也就是说,它应该是 pythonnet 的一个低级变体。最后,我们应该做一些像这样的事情
import clr
vm = clr.start_vm(".NET Framework")
ass = vm.add_reference("Python.Runtime", path=sth)
ass.call_static("Python.Runtime.Runtime", "Initialize", [my_python_dll, my_python_version])
clr.set_vm(vm)
clr.install_import_hook(ass)
首先,将整个库转换为纯粹的 .NET Standard (如果可能的话,也许会是 1.0,以保持对 .NET Framework 的兼容,最低 4.5)。这样,我们可以分发 (AFAICT) 单个 DLL,在所有目标中 (Mono >=4, CoreCLR >=1, .NET Framework >=4.5) 都可以加载。
因为我们已经在运行时类中动态地做了很多事情,所以我们可以更进一步,实际上去掉对所有正在运行的 Python 版本的静态检查。作为第一步,我们可以统一对 interop*.cs
文件的处理方式。它们在编译时生成,但最终我们只是通过对它们做偏移 “动态” 使用它们,我们可以轻易将这些偏移量存储为纯数据并一次性为所有关注的 Python 版本生成,也许只需要从 Github 检索相应的头文件,或者直接将它们包含在分发版中。然后,geninterop
代码应该为所有版本/标准/平台变体生成一个嵌入到 DLL 中的偏移量文件 (也许只是简单的 CSV 或类似的东西,可以将依赖降到最低)。
我们也可以删除对 DLL 的静态引用。据我所知,如果符号已经可用,DllImport
属性将不会尝试再次加载该 DLL。对于我们直接从 Python 中加载符号的使用方式来说,这是显而易见的的,在 Python 中,我们设置 DLL 名称为 "__Internal"
。因此,我们可以更进一步,总是将 DllImport
属性中的名称设置为类似这样的无意义的东西,并在使用 NativeMethods
垫片(shim)之前强制加载 DLL。 如果加载器甚至在使用类之前就尝试计算符号,我们可以将其提取到每个平台 (Windows vs Unix) 的一组分离的小 DLL 中,否则我们只能在这里实现一个接口的多个实现。
然后可以使用正常的运行时代码解析 DLL,理想情况下,它会像上面所述的一样显式地传递给我们,连同它的版本和运行时参数 s.t.。我们可以选择正确的 “模式” 和互操作偏移量。