diff -Naur tmp/Python-3.7.1/Python/ceval.c Python-3.7.1/Python/ceval.c --- tmp/Python-3.7.1/Python/ceval.c 2018-10-20 08:04:19.000000000 +0200 +++ Python-3.7.1/Python/ceval.c 2019-04-13 23:10:01.000000000 +0200 @@ -618,6 +618,10 @@ can be disabled on gcc by using the -fno-gcse flag (or possibly -fno-crossjumping). */ + + // iOS addition: computed gotos are a static variable (array of goto destinations) + // This can't work with iOS model, based on dynamic libraries. We've + // disabled the acceleration in pyconfig.h #ifdef DYNAMIC_EXECUTION_PROFILE #undef USE_COMPUTED_GOTOS @@ -1060,7 +1064,6 @@ } } #endif - switch (opcode) { /* BEWARE! @@ -2127,7 +2130,6 @@ } else { /* Slow-path if globals or builtins is not a dict */ - /* namespace 1: globals */ v = PyObject_GetItem(f->f_globals, name); if (v == NULL) { diff -Naur tmp/Python-3.7.1/Python/dynload_shlib.c Python-3.7.1/Python/dynload_shlib.c --- tmp/Python-3.7.1/Python/dynload_shlib.c 2018-10-20 08:04:19.000000000 +0200 +++ Python-3.7.1/Python/dynload_shlib.c 2019-06-06 16:52:01.000000000 +0200 @@ -62,16 +62,23 @@ char funcname[258]; char pathbuf[260]; int dlopenflags=0; - + if (strchr(pathname, '/') == NULL) { +#ifndef TARGET_OS_IPHONE /* Prefix bare filename with "./" */ PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname); +#else + /* Prefix bare filenames with "$APPDIR/Frameworks/" */ + /* (the only place where we can put dynamic libraries on iOS */ + fprintf(stderr, "_PyImport_FindSharedFuncptr: %s\n", pathname); + PyOS_snprintf(pathbuf, sizeof(pathbuf), "%s/Frameworks/%s", getenv("APPDIR"), pathname); + fprintf(stderr, "_PyImport_FindSharedFuncptr, new path: %s\n", pathbuf); +#endif pathname = pathbuf; } PyOS_snprintf(funcname, sizeof(funcname), LEAD_UNDERSCORE "%.20s_%.200s", prefix, shortname); - if (fp != NULL) { int i; struct _Py_stat_struct status; @@ -102,6 +109,8 @@ const char *error = dlerror(); if (error == NULL) error = "unknown dlopen() error"; + // iOS, debug: + fprintf(stderr, "dlopen error: %s\n", error); error_ob = PyUnicode_FromString(error); if (error_ob == NULL) return NULL; diff -Naur tmp/Python-3.7.1/Python/fileutils.c Python-3.7.1/Python/fileutils.c --- tmp/Python-3.7.1/Python/fileutils.c 2018-10-20 08:04:19.000000000 +0200 +++ Python-3.7.1/Python/fileutils.c 2019-05-08 20:31:54.000000000 +0200 @@ -1375,7 +1375,7 @@ count = PY_SSIZE_T_MAX; } #endif - + _Py_BEGIN_SUPPRESS_IPH do { Py_BEGIN_ALLOW_THREADS diff -Naur tmp/Python-3.7.1/Python/getplatform.c Python-3.7.1/Python/getplatform.c --- tmp/Python-3.7.1/Python/getplatform.c 2018-10-20 08:04:19.000000000 +0200 +++ Python-3.7.1/Python/getplatform.c 2018-12-20 23:39:32.000000000 +0100 @@ -2,7 +2,7 @@ #include "Python.h" #ifndef PLATFORM -#define PLATFORM "unknown" +#define PLATFORM "darwin" #endif const char * diff -Naur tmp/Python-3.7.1/Python/import.c Python-3.7.1/Python/import.c --- tmp/Python-3.7.1/Python/import.c 2018-10-20 08:04:19.000000000 +0200 +++ Python-3.7.1/Python/import.c 2019-06-06 16:39:39.000000000 +0200 @@ -391,8 +391,6 @@ NULL }; -/* Un-initialize things, as good as we can */ - void PyImport_Cleanup(void) { @@ -413,7 +411,7 @@ destruction order. Sigh. */ /* XXX Perhaps these precautions are obsolete. Who knows? */ - + if (Py_VerboseFlag) PySys_WriteStderr("# clear builtins._\n"); if (PyDict_SetItemString(interp->builtins, "_", Py_None) < 0) { @@ -557,6 +555,18 @@ PySys_FormatStderr("# cleanup[3] wiping %U\n", name); _PyModule_Clear(mod); Py_DECREF(mod); +#if TARGET_OS_IPHONE + // Modules created with Cython + PEP489 have strange issues with number of references + // which prevent the freefunc function from being called. + // We explicitly call the freefunc function here, before the dictionary is cleared. + // (otherwise, "name" is gone) + // Thos here is just for debugging, the module erasure is done in moduleobject.c + const char* utf8name = PyUnicode_AsUTF8(name); + if ((strncmp(utf8name, "pandas.", 7) == 0) || (strncmp(utf8name, "numpy.", 6) == 0)) { + // fprintf(stderr, "We have a module = %x name = %s refCount = %zd\n", mod, utf8name, mod->ob_refcnt); + // if (mod->md_def && mod->md_def->m_free) mod->md_def->m_free(mod); + } +#endif } Py_DECREF(weaklist); } @@ -576,7 +586,9 @@ Py_DECREF(modules); /* Once more */ - _PyGC_CollectNoFail(); + Py_VerboseFlag = 0; + _PyGC_CollectNoFail(); // The line destroying all remaining modules + Py_VerboseFlag = 0; #undef CLEAR_MODULE #undef STORE_MODULE_WEAKREF @@ -1367,6 +1379,7 @@ { PyObject *nameobj; int ret; + nameobj = PyUnicode_InternFromString(name); if (nameobj == NULL) return -1; @@ -1482,7 +1495,7 @@ Py_ssize_t last_dot; PyObject *base; int level_up; - + if (globals == NULL) { PyErr_SetString(PyExc_KeyError, "'__name__' not in globals"); goto error; @@ -2118,6 +2131,9 @@ Create an extension module. [clinic start generated code]*/ +#ifdef TARGET_OS_IPHONE + extern void Py_GetArgcArgv(int *argc, wchar_t ***argv); +#endif static PyObject * _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file) @@ -2136,6 +2152,31 @@ Py_DECREF(name); return NULL; } +#ifdef TARGET_OS_IPHONE + // fprintf(stderr, "_imp_create_dynamic_impl, name = "); + // PyObject_Print(name, stderr, 0); + // PyObject_Print(name, stderr, Py_PRINT_RAW); + // fprintf(stderr, " path = "); + // PyObject_Print(path, stderr, 0); + // PyObject_Print(path, stderr, Py_PRINT_RAW); + // fprintf(stderr, " file = "); + // PyObject_Print(file, stderr, 0); + // fprintf(stderr, " \n"); + char newPathString[MAXPATHLEN]; + int argc; + wchar_t **argv_orig; + Py_GetArgcArgv(&argc, &argv_orig); + const char* nameC = PyUnicode_AsUTF8(name); + wchar_t pythonName[12]; + wcscpy(pythonName, argv_orig[0]); + if (wcscmp(pythonName, L"python3") == 0) { + wcscpy(pythonName, L"python3_ios"); + } + sprintf(newPathString, "%s/Frameworks/%S-%s.framework/%S-%s", getenv("APPDIR"), pythonName, nameC, pythonName, nameC); + // fprintf(stderr, "New path: %s\n", newPathString); + path = PyUnicode_FromString(newPathString); + PyObject_SetAttrString(spec, "origin", path); +#endif mod = _PyImport_FindExtensionObject(name, path); if (mod != NULL) { @@ -2148,6 +2189,9 @@ if (file != NULL) { fp = _Py_fopen_obj(path, "r"); if (fp == NULL) { +#ifdef TARGET_OS_IPHONE + fprintf(stderr, " _Py_fopen_obj is NULL (logical) "); +#endif Py_DECREF(name); Py_DECREF(path); return NULL; diff -Naur tmp/Python-3.7.1/Python/pathconfig.c Python-3.7.1/Python/pathconfig.c --- tmp/Python-3.7.1/Python/pathconfig.c 2018-10-20 08:04:19.000000000 +0200 +++ Python-3.7.1/Python/pathconfig.c 2019-04-06 22:39:42.000000000 +0200 @@ -277,6 +277,7 @@ #endif argv0 = argv[0]; + if (argc > 0 && argv0 != NULL) { have_module_arg = (wcscmp(argv0, L"-m") == 0); have_script_arg = !have_module_arg && (wcscmp(argv0, L"-c") != 0); diff -Naur tmp/Python-3.7.1/Python/pylifecycle.c Python-3.7.1/Python/pylifecycle.c --- tmp/Python-3.7.1/Python/pylifecycle.c 2018-10-20 08:04:19.000000000 +0200 +++ Python-3.7.1/Python/pylifecycle.c 2019-05-02 22:41:04.000000000 +0200 @@ -893,6 +893,7 @@ * Other errors should be reported as normal Python exceptions with a * non-zero return code. */ + _PyInitError _Py_InitializeMainInterpreter(PyInterpreterState *interp, const _PyMainInterpreterConfig *config) @@ -2097,7 +2098,7 @@ static void _Py_NO_RETURN fatal_error(const char *prefix, const char *msg, int status) { - const int fd = fileno(stderr); + const int fd = (thread_stderr != NULL) ? fileno(thread_stderr) : fileno(stderr); static int reentrant = 0; if (reentrant) { @@ -2107,19 +2108,19 @@ } reentrant = 1; - fprintf(stderr, "Fatal Python error: "); + fprintf(thread_stderr, "Fatal Python error: "); if (prefix) { - fputs(prefix, stderr); - fputs(": ", stderr); + fputs(prefix, thread_stderr); + fputs(": ", thread_stderr); } if (msg) { - fputs(msg, stderr); + fputs(msg, thread_stderr); } else { - fprintf(stderr, ""); + fprintf(thread_stderr, ""); } - fputs("\n", stderr); - fflush(stderr); /* it helps in Windows debug build */ + fputs("\n", thread_stderr); + fflush(thread_stderr); /* it helps in Windows debug build */ /* Print the exception (if an exception is set) with its traceback, * or display the current Python stack. */