Files
mtgodot-poc/extension/third_party/cpython-2.7.18/PC/dl_nt.c
T
shenleiandClaude Opus 5 5fad769ee8 port 2P step 1: vendor CPython 2.7.18 as the mtpython static library
The embedded 40250 script layer needs its own interpreter on five platforms.
2.7 is end-of-life, so nothing can be fetched from the target SDKs and the
source is vendored (official 2.7.18 tarball, trimmed to 25MB; Lib/ stays for
step 3's python27.zip).

cpython-2.7.18/CMakeLists.txt builds one `mtpython` static library from exactly
the 133 objects the reference libpython2.7.a contains, off by default behind
-DMTGODOT_EMBED_PYTHON=ON. The source list and the built-in module table
(config/config.c, 39 entries) are shared; pyconfig.h is a probe result and is
not, so each platform keeps its own under config/<platform>/, regenerated by
tools/py_embed/gen_pyconfig.sh and checked against the shared table.

Three vendor patches, documented in docs/THIRD-PARTY.md: configure/configure.ac
learn arm64 on macOS, and posixmodule.c undefines the process-control calls it
hard-defines past pyconfig.h when building for iOS.

macOS (ctest python.embed: every builtin imports, codecs and pickle work off the
vendored Lib/), Android arm64 and iOS arm64 build. Linux needs a Linux host and
Windows needs a MinGW-vs-MSVC decision; both are noted for step 4.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 08:27:35 +09:00

112 lines
4.3 KiB
C

/*
Entry point for the Windows NT DLL.
About the only reason for having this, is so initall() can automatically
be called, removing that burden (and possible source of frustration if
forgotten) from the programmer.
*/
#include "Python.h"
#include "windows.h"
#ifdef Py_ENABLE_SHARED
char dllVersionBuffer[16] = ""; // a private buffer
// Python Globals
HMODULE PyWin_DLLhModule = NULL;
const char *PyWin_DLLVersionString = dllVersionBuffer;
// Windows "Activation Context" work:
// Our .pyd extension modules are generally built without a manifest (ie,
// those included with Python and those built with a default distutils.
// This requires we perform some "activation context" magic when loading our
// extensions. In summary:
// * As our DLL loads we save the context being used.
// * Before loading our extensions we re-activate our saved context.
// * After extension load is complete we restore the old context.
// As an added complication, this magic only works on XP or later - we simply
// use the existence (or not) of the relevant function pointers from kernel32.
// See bug 4566 (http://python.org/sf/4566) for more details.
typedef BOOL (WINAPI * PFN_GETCURRENTACTCTX)(HANDLE *);
typedef BOOL (WINAPI * PFN_ACTIVATEACTCTX)(HANDLE, ULONG_PTR *);
typedef BOOL (WINAPI * PFN_DEACTIVATEACTCTX)(DWORD, ULONG_PTR);
typedef void (WINAPI * PFN_ADDREFACTCTX)(HANDLE);
typedef void (WINAPI * PFN_RELEASEACTCTX)(HANDLE);
// locals and function pointers for this activation context magic.
static HANDLE PyWin_DLLhActivationContext = NULL; // one day it might be public
static PFN_GETCURRENTACTCTX pfnGetCurrentActCtx = NULL;
static PFN_ACTIVATEACTCTX pfnActivateActCtx = NULL;
static PFN_DEACTIVATEACTCTX pfnDeactivateActCtx = NULL;
static PFN_ADDREFACTCTX pfnAddRefActCtx = NULL;
static PFN_RELEASEACTCTX pfnReleaseActCtx = NULL;
void _LoadActCtxPointers()
{
HINSTANCE hKernel32 = GetModuleHandleW(L"kernel32.dll");
if (hKernel32)
pfnGetCurrentActCtx = (PFN_GETCURRENTACTCTX) GetProcAddress(hKernel32, "GetCurrentActCtx");
// If we can't load GetCurrentActCtx (ie, pre XP) , don't bother with the rest.
if (pfnGetCurrentActCtx) {
pfnActivateActCtx = (PFN_ACTIVATEACTCTX) GetProcAddress(hKernel32, "ActivateActCtx");
pfnDeactivateActCtx = (PFN_DEACTIVATEACTCTX) GetProcAddress(hKernel32, "DeactivateActCtx");
pfnAddRefActCtx = (PFN_ADDREFACTCTX) GetProcAddress(hKernel32, "AddRefActCtx");
pfnReleaseActCtx = (PFN_RELEASEACTCTX) GetProcAddress(hKernel32, "ReleaseActCtx");
}
}
ULONG_PTR _Py_ActivateActCtx()
{
ULONG_PTR ret = 0;
if (PyWin_DLLhActivationContext && pfnActivateActCtx)
if (!(*pfnActivateActCtx)(PyWin_DLLhActivationContext, &ret)) {
OutputDebugString("Python failed to activate the activation context before loading a DLL\n");
ret = 0; // no promise the failing function didn't change it!
}
return ret;
}
void _Py_DeactivateActCtx(ULONG_PTR cookie)
{
if (cookie && pfnDeactivateActCtx)
if (!(*pfnDeactivateActCtx)(0, cookie))
OutputDebugString("Python failed to de-activate the activation context\n");
}
BOOL WINAPI DllMain (HANDLE hInst,
ULONG ul_reason_for_call,
LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
PyWin_DLLhModule = hInst;
// 1000 is a magic number I picked out of the air. Could do with a #define, I spose...
LoadString(hInst, 1000, dllVersionBuffer, sizeof(dllVersionBuffer));
// and capture our activation context for use when loading extensions.
_LoadActCtxPointers();
if (pfnGetCurrentActCtx && pfnAddRefActCtx)
if ((*pfnGetCurrentActCtx)(&PyWin_DLLhActivationContext)) {
(*pfnAddRefActCtx)(PyWin_DLLhActivationContext);
}
else {
OutputDebugString("Python failed to load the default "
"activation context\n");
return FALSE;
}
break;
case DLL_PROCESS_DETACH:
if (pfnReleaseActCtx)
(*pfnReleaseActCtx)(PyWin_DLLhActivationContext);
break;
}
return TRUE;
}
#endif /* Py_ENABLE_SHARED */