Last active
December 30, 2022 18:34
-
-
Save filmor/cf8a02aefff58be09a57ad2eca3cc246 to your computer and use it in GitHub Desktop.
Initialize CLR via ctypes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import subprocess\n", | |
"import re\n", | |
"from collections import namedtuple\n", | |
"import os" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"Runtime = namedtuple(\"Runtime\", \"name version path\")\n", | |
"\n", | |
"runtimes_l = subprocess.check_output(\"dotnet --list-runtimes\")\n", | |
"runtimes_l = runtimes_l.decode(\"utf8\").splitlines()\n", | |
"\n", | |
"runtimes = []\n", | |
"\n", | |
"for l in runtimes_l:\n", | |
" name, version, path = l.split(' ', 2)\n", | |
" runtimes.append(\n", | |
" Runtime(name=name, version=version, path=os.path.join(path[1:-1], version))\n", | |
" )\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Runtime(name='Microsoft.NETCore.App', version='2.2.3', path='C:\\\\Program Files\\\\dotnet\\\\shared\\\\Microsoft.NETCore.App\\\\2.2.3')\n" | |
] | |
} | |
], | |
"source": [ | |
"rt = runtimes[-1]\n", | |
"print(rt)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import cffi\n", | |
"\n", | |
"ffi = cffi.FFI()\n", | |
"ffi.cdef(\"\"\"\n", | |
"__stdcall int coreclr_initialize(\n", | |
" const char* exePath,\n", | |
" const char* appDomainFriendlyName,\n", | |
" int propertyCount,\n", | |
" const char** propertyKeys,\n", | |
" const char** propertyValues,\n", | |
" void** hostHandle,\n", | |
" unsigned* domainId\n", | |
");\n", | |
"\n", | |
"__stdcall int coreclr_execute_assembly(\n", | |
" void* hostHandle,\n", | |
" unsigned int domainId,\n", | |
" int argc,\n", | |
" const char** argv,\n", | |
" const char* managedAssemblyPath,\n", | |
" unsigned int* exitCode\n", | |
");\n", | |
"\n", | |
"__stdcall int coreclr_create_delegate(\n", | |
" void* hostHandle,\n", | |
" unsigned int domainId,\n", | |
" const char* entryPointAssemblyName,\n", | |
" const char* entryPointTypeName,\n", | |
" const char* entryPointMethodName,\n", | |
" void** delegate\n", | |
");\n", | |
"\n", | |
"__stdcall int coreclr_shutdown(void* hostHandle, unsigned int domainId);\n", | |
"\"\"\")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import sys, glob\n", | |
"\n", | |
"coreclr = ffi.dlopen(os.path.join(rt.path, \"coreclr.dll\"))\n", | |
"\n", | |
"handle = ffi.new(\"void **\")\n", | |
"domain = ffi.new(\"unsigned *\")\n", | |
"\n", | |
"properties = {\n", | |
" \"APP_PATHS\": r\"c:\\git\\pythonnet\\bin\",\n", | |
" \"TRUSTED_PLATFORM_ASSEMBLIES\": \";\".join(glob.glob(rt.path + \"/*.dll\"))\n", | |
"}\n", | |
"\n", | |
"err_code = coreclr.coreclr_initialize(\n", | |
" sys.executable.encode(\"utf8\"),\n", | |
" b\"Python\",\n", | |
" len(properties),\n", | |
" list(ffi.new(\"char[]\", i.encode(\"utf8\")) for i in properties.keys()),\n", | |
" list(ffi.new(\"char[]\", i.encode(\"utf8\")) for i in properties.values()),\n", | |
" handle,\n", | |
" domain\n", | |
")\n", | |
"\n", | |
"if err_code != 0:\n", | |
" del handle\n", | |
" del domain\n", | |
" raise RuntimeError(err_code)\n", | |
"\n", | |
"handle = handle[0]\n", | |
"domain = domain[0]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# coreclr.coreclr_shutdown(handle, domain)\n", | |
"# ffi.dlclose(coreclr)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"<cdata 'void(*)()' 0x00007FFE2658304C>" | |
] | |
}, | |
"execution_count": 7, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"func_ptr = ffi.new(\"void**\")\n", | |
"\n", | |
"res = coreclr.coreclr_create_delegate(\n", | |
" handle,\n", | |
" domain,\n", | |
" b\"Python.Runtime\",\n", | |
" b\"Python.Runtime.PythonEngine\",\n", | |
" b\"InitExt\",\n", | |
" func_ptr\n", | |
")\n", | |
"\n", | |
"if res == 0:\n", | |
" func = ffi.cast(\"void* (*func)()\", func_ptr[0])\n", | |
"else:\n", | |
" import numpy as np\n", | |
" raise RuntimeError(f\"Error in create delegate: {hex(np.uint32(res))}\")\n", | |
"\n", | |
"func" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"14412" | |
] | |
}, | |
"execution_count": 8, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"import os\n", | |
"os.getpid()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"func()" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.6.8" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment