/* int main(int argc, char **argv) { */ int main(int argc, char *argv[]) { char *env_argument = NULL; char *env_entrypoint = NULL; char *env_logname = NULL; char entrypoint[ENTRYPOINT_MAXLEN]; int ret = 0; FILE *fd; LOGP("Initializing Python for Android"); // Set a couple of built-in environment vars: setenv("P4A_BOOTSTRAP", bootstrap_name, 1); // env var to identify p4a to applications env_argument = getenv("ANDROID_ARGUMENT"); setenv("ANDROID_APP_PATH", env_argument, 1); env_entrypoint = getenv("ANDROID_ENTRYPOINT"); env_logname = getenv("PYTHON_NAME"); if (!getenv("ANDROID_UNPACK")) { /* ANDROID_UNPACK currently isn't set in services */ setenv("ANDROID_UNPACK", env_argument, 1); } if (env_logname == NULL) { env_logname = "python"; setenv("PYTHON_NAME", "python", 1); } // Set additional file-provided environment vars: LOGP("Setting additional env vars from p4a_env_vars.txt"); char env_file_path[256]; snprintf(env_file_path, sizeof(env_file_path), "%s/p4a_env_vars.txt", getenv("ANDROID_UNPACK")); FILE *env_file_fd = fopen(env_file_path, "r"); if (env_file_fd) { char* line = NULL; size_t len = 0; while (getline(&line, &len, env_file_fd) != -1) { if (strlen(line) > 0) { char *eqsubstr = strstr(line, "="); if (eqsubstr) { size_t eq_pos = eqsubstr - line; // Extract name: char env_name[256]; strncpy(env_name, line, sizeof(env_name)); env_name[eq_pos] = '\0'; // Extract value (with line break removed: char env_value[256]; strncpy(env_value, (char*)(line + eq_pos + 1), sizeof(env_value)); if (strlen(env_value) > 0 && env_value[strlen(env_value)-1] == '\n') { env_value[strlen(env_value)-1] = '\0'; if (strlen(env_value) > 0 && env_value[strlen(env_value)-1] == '\r') { // Also remove windows line breaks (\r\n) env_value[strlen(env_value)-1] = '\0'; } } // Set value: setenv(env_name, env_value, 1); } } } fclose(env_file_fd); } else { LOGP("Warning: no p4a_env_vars.txt found / failed to open!"); } LOGP("Changing directory to the one provided by ANDROID_ARGUMENT"); LOGP(env_argument); chdir(env_argument); #if PY_MAJOR_VERSION < 3 Py_NoSiteFlag=1; #endif #if PY_MAJOR_VERSION < 3 Py_SetProgramName("android_python"); #else Py_SetProgramName(L"android_python"); #endif #if PY_MAJOR_VERSION >= 3 /* our logging module for android */ PyImport_AppendInittab("androidembed", initandroidembed); #endif LOGP("Preparing to initialize python"); // Set up the python path char paths[256]; char crystax_python_dir[256]; snprintf(crystax_python_dir, 256, "%s/crystax_python", getenv("ANDROID_UNPACK")); char python_bundle_dir[256]; snprintf(python_bundle_dir, 256, "%s/_python_bundle", getenv("ANDROID_UNPACK")); if (dir_exists(crystax_python_dir) || dir_exists(python_bundle_dir)) { if (dir_exists(crystax_python_dir)) { LOGP("crystax_python exists"); snprintf(paths, 256, "%s/stdlib.zip:%s/modules", crystax_python_dir, crystax_python_dir); } if (dir_exists(python_bundle_dir)) { LOGP("_python_bundle dir exists"); snprintf(paths, 256, "%s/stdlib.zip:%s/modules", python_bundle_dir, python_bundle_dir); } LOGP("calculated paths to be..."); LOGP(paths); #if PY_MAJOR_VERSION >= 3 wchar_t *wchar_paths = Py_DecodeLocale(paths, NULL); Py_SetPath(wchar_paths); #endif LOGP("set wchar paths..."); } else { // We do not expect to see crystax_python any more, so no point // reminding the user about it. If it does exist, we'll have // logged it earlier. LOGP("_python_bundle does not exist"); } Py_Initialize(); #if PY_MAJOR_VERSION < 3 // Can't Py_SetPath in python2 but we can set PySys_SetPath, which must // be applied after Py_Initialize rather than before like Py_SetPath #if PY_MICRO_VERSION >= 15 // Only for python native-build PySys_SetPath(paths); #endif PySys_SetArgv(argc, argv); #endif LOGP("Initialized python"); /* ensure threads will work. */ LOGP("AND: Init threads"); PyEval_InitThreads(); #if PY_MAJOR_VERSION < 3 initandroidembed(); #endif PyRun_SimpleString("import androidembed\nandroidembed.log('testing python " "print redirection')"); /* inject our bootstrap code to redirect python stdin/stdout * replace sys.path with our path */ PyRun_SimpleString("import sys, posix\n"); if (dir_exists("lib")) { /* If we built our own python, set up the paths correctly. * This is only the case if we are using the python2legacy recipe */ LOGP("Setting up python from ANDROID_APP_PATH"); PyRun_SimpleString("private = posix.environ['ANDROID_APP_PATH']\n" "argument = posix.environ['ANDROID_ARGUMENT']\n" "sys.path[:] = [ \n" " private + '/lib/python27.zip', \n" " private + '/lib/python2.7/', \n" " private + '/lib/python2.7/lib-dynload/', \n" " private + '/lib/python2.7/site-packages/', \n" " argument ]\n"); } char add_site_packages_dir[256]; if (dir_exists(crystax_python_dir)) { snprintf(add_site_packages_dir, 256, "sys.path.append('%s/site-packages')", crystax_python_dir); PyRun_SimpleString("import sys\n" "sys.argv = ['notaninterpreterreally']\n" "from os.path import realpath, join, dirname"); PyRun_SimpleString(add_site_packages_dir); /* "sys.path.append(join(dirname(realpath(__file__)), 'site-packages'))") */ PyRun_SimpleString("sys.path = ['.'] + sys.path"); } if (dir_exists(python_bundle_dir)) { snprintf(add_site_packages_dir, 256, "sys.path.append('%s/site-packages')", python_bundle_dir); PyRun_SimpleString("import sys\n" "sys.argv = ['notaninterpreterreally']\n" "from os.path import realpath, join, dirname"); PyRun_SimpleString(add_site_packages_dir); /* "sys.path.append(join(dirname(realpath(__file__)), 'site-packages'))") */ PyRun_SimpleString("sys.path = ['.'] + sys.path"); } PyRun_SimpleString( "class LogFile(object):\n" " def __init__(self):\n" " self.buffer = ''\n" " def write(self, s):\n" " s = self.buffer + s\n" " lines = s.split(\"\\n\")\n" " for l in lines[:-1]:\n" " androidembed.log(l)\n" " self.buffer = lines[-1]\n" " def flush(self):\n" " return\n" "sys.stdout = sys.stderr = LogFile()\n" "print('Android path', sys.path)\n" "import os\n" "print('os.environ is', os.environ)\n" "print('Android kivy bootstrap done. __name__ is', __name__)"); #if PY_MAJOR_VERSION < 3 PyRun_SimpleString("import site; print site.getsitepackages()\n"); #endif LOGP("AND: Ran string"); /* run it ! */ LOGP("Run user program, change dir and execute entrypoint"); /* Get the entrypoint, search the .pyo then .py */ char *dot = strrchr(env_entrypoint, '.'); #if PY_MAJOR_VERSION > 2 char *ext = ".pyc"; #else char *ext = ".pyo"; #endif if (dot <= 0) { LOGP("Invalid entrypoint, abort."); return -1; } if (strlen(env_entrypoint) > ENTRYPOINT_MAXLEN - 2) { LOGP("Entrypoint path is too long, try increasing ENTRYPOINT_MAXLEN."); return -1; } if (!strcmp(dot, ext)) { if (!file_exists(env_entrypoint)) { /* fallback on .py */ strcpy(entrypoint, env_entrypoint); entrypoint[strlen(env_entrypoint) - 1] = '\0'; LOGP(entrypoint); if (!file_exists(entrypoint)) { LOGP("Entrypoint not found (.pyc/.pyo, fallback on .py), abort"); return -1; } } else { strcpy(entrypoint, env_entrypoint); } } else if (!strcmp(dot, ".py")) { /* if .py is passed, check the pyo version first */ strcpy(entrypoint, env_entrypoint); entrypoint[strlen(env_entrypoint) + 1] = '\0'; #if PY_MAJOR_VERSION > 2 entrypoint[strlen(env_entrypoint)] = 'c'; #else entrypoint[strlen(env_entrypoint)] = 'o'; #endif if (!file_exists(entrypoint)) { /* fallback on pure python version */ if (!file_exists(env_entrypoint)) { LOGP("Entrypoint not found (.py), abort."); return -1; } strcpy(entrypoint, env_entrypoint); } } else { LOGP("Entrypoint have an invalid extension (must be .py or .pyc/.pyo), abort."); return -1; } // LOGP("Entrypoint is:"); // LOGP(entrypoint); fd = fopen(entrypoint, "r"); if (fd == NULL) { LOGP("Open the entrypoint failed"); LOGP(entrypoint); return -1; } /* run python ! */ ret = PyRun_SimpleFile(fd, entrypoint); fclose(fd); if (PyErr_Occurred() != NULL) { ret = 1; PyErr_Print(); /* This exits with the right code if SystemExit. */ PyObject *f = PySys_GetObject("stdout"); if (PyFile_WriteString( "\n", f)) /* python2 used Py_FlushLine, but this no longer exists */ PyErr_Clear(); } LOGP("Python for android ended."); /* Shut down: since regular shutdown causes issues sometimes (seems to be an incomplete shutdown breaking next launch) we'll use sys.exit(ret) to shutdown, since that one works. Reference discussion: https://github.com/kivy/kivy/pull/6107#issue-246120816 */ char terminatecmd[256]; snprintf( terminatecmd, sizeof(terminatecmd), "import sys; sys.exit(%d)\n", ret ); PyRun_SimpleString(terminatecmd); /* This should never actually be reached, but we'll leave the clean-up * here just to be safe. */ #if PY_MAJOR_VERSION < 3 Py_Finalize(); LOGP("Unexpectedly reached Py_FinalizeEx(), but was successful."); #else if (Py_FinalizeEx() != 0) // properly check success on Python 3 LOGP("Unexpectedly reached Py_FinalizeEx(), and got error!"); else LOGP("Unexpectedly reached Py_FinalizeEx(), but was successful."); #endif return ret; }
/* int main(int argc, char **argv) { */ int main(int argc, char *argv[]) { char *env_argument = NULL; char *env_entrypoint = NULL; char *env_logname = NULL; char entrypoint[ENTRYPOINT_MAXLEN]; int ret = 0; FILE *fd; setenv("P4A_BOOTSTRAP", "SDL2", 1); // env var to identify p4a to applications LOGP("Initializing Python for Android"); env_argument = getenv("ANDROID_ARGUMENT"); setenv("ANDROID_APP_PATH", env_argument, 1); env_entrypoint = getenv("ANDROID_ENTRYPOINT"); env_logname = getenv("PYTHON_NAME"); if (!getenv("ANDROID_UNPACK")) { /* ANDROID_UNPACK currently isn't set in services */ setenv("ANDROID_UNPACK", env_argument, 1); } if (env_logname == NULL) { env_logname = "python"; setenv("PYTHON_NAME", "python", 1); } LOGP("Changing directory to the one provided by ANDROID_ARGUMENT"); LOGP(env_argument); chdir(env_argument); Py_SetProgramName(L"android_python"); #if PY_MAJOR_VERSION >= 3 /* our logging module for android */ PyImport_AppendInittab("androidembed", initandroidembed); #endif LOGP("Preparing to initialize python"); // Set up the python path char paths[256]; char crystax_python_dir[256]; snprintf(crystax_python_dir, 256, "%s/crystax_python", getenv("ANDROID_UNPACK")); char python_bundle_dir[256]; snprintf(python_bundle_dir, 256, "%s/_python_bundle", getenv("ANDROID_UNPACK")); if (dir_exists(crystax_python_dir) || dir_exists(python_bundle_dir)) { if (dir_exists(crystax_python_dir)) { LOGP("crystax_python exists"); snprintf(paths, 256, "%s/stdlib.zip:%s/modules", crystax_python_dir, crystax_python_dir); } if (dir_exists(python_bundle_dir)) { LOGP("_python_bundle dir exists"); snprintf(paths, 256, "%s/stdlib.zip:%s/modules", python_bundle_dir, python_bundle_dir); } LOGP("calculated paths to be..."); LOGP(paths); #if PY_MAJOR_VERSION >= 3 wchar_t *wchar_paths = Py_DecodeLocale(paths, NULL); Py_SetPath(wchar_paths); #else char *wchar_paths = paths; LOGP("Can't Py_SetPath in python2, so crystax python2 doesn't work yet"); exit(1); #endif LOGP("set wchar paths..."); } else { // We do not expect to see crystax_python any more, so no point // reminding the user about it. If it does exist, we'll have // logged it earlier. LOGP("_python_bundle does not exist"); } Py_Initialize(); #if PY_MAJOR_VERSION < 3 PySys_SetArgv(argc, argv); #endif LOGP("Initialized python"); /* ensure threads will work. */ LOGP("AND: Init threads"); PyEval_InitThreads(); #if PY_MAJOR_VERSION < 3 initandroidembed(); #endif PyRun_SimpleString("import androidembed\nandroidembed.log('testing python " "print redirection')"); /* inject our bootstrap code to redirect python stdin/stdout * replace sys.path with our path */ PyRun_SimpleString("import sys, posix\n"); if (dir_exists("lib")) { /* If we built our own python, set up the paths correctly */ LOGP("Setting up python from ANDROID_PRIVATE"); PyRun_SimpleString("private = posix.environ['ANDROID_APP_PATH']\n" "argument = posix.environ['ANDROID_ARGUMENT']\n" "sys.path[:] = [ \n" " private + '/lib/python27.zip', \n" " private + '/lib/python2.7/', \n" " private + '/lib/python2.7/lib-dynload/', \n" " private + '/lib/python2.7/site-packages/', \n" " argument ]\n"); } char add_site_packages_dir[256]; if (dir_exists(crystax_python_dir)) { snprintf(add_site_packages_dir, 256, "sys.path.append('%s/site-packages')", crystax_python_dir); PyRun_SimpleString("import sys\n" "sys.argv = ['notaninterpreterreally']\n" "from os.path import realpath, join, dirname"); PyRun_SimpleString(add_site_packages_dir); /* "sys.path.append(join(dirname(realpath(__file__)), 'site-packages'))") */ PyRun_SimpleString("sys.path = ['.'] + sys.path"); } if (dir_exists(python_bundle_dir)) { snprintf(add_site_packages_dir, 256, "sys.path.append('%s/site-packages')", python_bundle_dir); PyRun_SimpleString("import sys\n" "sys.argv = ['notaninterpreterreally']\n" "from os.path import realpath, join, dirname"); PyRun_SimpleString(add_site_packages_dir); /* "sys.path.append(join(dirname(realpath(__file__)), 'site-packages'))") */ PyRun_SimpleString("sys.path = ['.'] + sys.path"); } PyRun_SimpleString( "class LogFile(object):\n" " def __init__(self):\n" " self.buffer = ''\n" " def write(self, s):\n" " s = self.buffer + s\n" " lines = s.split(\"\\n\")\n" " for l in lines[:-1]:\n" " androidembed.log(l)\n" " self.buffer = lines[-1]\n" " def flush(self):\n" " return\n" "sys.stdout = sys.stderr = LogFile()\n" "print('Android path', sys.path)\n" "import os\n" "print('os.environ is', os.environ)\n" "print('Android kivy bootstrap done. __name__ is', __name__)"); #if PY_MAJOR_VERSION < 3 PyRun_SimpleString("import site; print site.getsitepackages()\n"); #endif LOGP("AND: Ran string"); /* run it ! */ LOGP("Run user program, change dir and execute entrypoint"); /* Get the entrypoint, search the .pyo then .py */ char *dot = strrchr(env_entrypoint, '.'); if (dot <= 0) { LOGP("Invalid entrypoint, abort."); return -1; } if (strlen(env_entrypoint) > ENTRYPOINT_MAXLEN - 2) { LOGP("Entrypoint path is too long, try increasing ENTRYPOINT_MAXLEN."); return -1; } if (!strcmp(dot, ".pyo")) { if (!file_exists(env_entrypoint)) { /* fallback on .py */ strcpy(entrypoint, env_entrypoint); entrypoint[strlen(env_entrypoint) - 1] = '\0'; LOGP(entrypoint); if (!file_exists(entrypoint)) { LOGP("Entrypoint not found (.pyo, fallback on .py), abort"); return -1; } } else { strcpy(entrypoint, env_entrypoint); } } else if (!strcmp(dot, ".py")) { /* if .py is passed, check the pyo version first */ strcpy(entrypoint, env_entrypoint); entrypoint[strlen(env_entrypoint) + 1] = '\0'; entrypoint[strlen(env_entrypoint)] = 'o'; if (!file_exists(entrypoint)) { /* fallback on pure python version */ if (!file_exists(env_entrypoint)) { LOGP("Entrypoint not found (.py), abort."); return -1; } strcpy(entrypoint, env_entrypoint); } } else { LOGP("Entrypoint have an invalid extension (must be .py or .pyo), abort."); return -1; } // LOGP("Entrypoint is:"); // LOGP(entrypoint); fd = fopen(entrypoint, "r"); if (fd == NULL) { LOGP("Open the entrypoint failed"); LOGP(entrypoint); return -1; } /* run python ! */ ret = PyRun_SimpleFile(fd, entrypoint); if (PyErr_Occurred() != NULL) { ret = 1; PyErr_Print(); /* This exits with the right code if SystemExit. */ PyObject *f = PySys_GetObject("stdout"); if (PyFile_WriteString( "\n", f)) /* python2 used Py_FlushLine, but this no longer exists */ PyErr_Clear(); } /* close everything */ Py_Finalize(); fclose(fd); LOGP("Python for android ended."); return ret; }
/* int main(int argc, char **argv) { */ int main(int argc, char *argv[]) { char *env_argument = NULL; int ret = 0; FILE *fd; /* AND: Several filepaths are hardcoded here, these must be made configurable */ /* AND: P4A uses env vars...not sure what's best */ LOG("Initialize Python for Android"); /* env_argument = "/data/data/org.kivy.android/files"; */ env_argument = getenv("ANDROID_ARGUMENT"); /* setenv("ANDROID_APP_PATH", env_argument, 1); */ /* setenv("ANDROID_ARGUMENT", env_argument, 1); */ /* setenv("ANDROID_PRIVATE", env_argument, 1); */ /* setenv("ANDROID_APP_PATH", env_argument, 1); */ /* setenv("PYTHONHOME", env_argument, 1); */ /* setenv("PYTHONPATH", "/data/data/org.kivy.android/files:/data/data/org.kivy.android/files/lib", 1); */ /* LOG("AND: Set env vars"); */ /* LOG(argv[0]); */ /* LOG("AND: That was argv 0"); */ //setenv("PYTHONVERBOSE", "2", 1); LOG("Changing directory to the one provided by ANDROID_ARGUMENT"); LOG(env_argument); chdir(env_argument); Py_SetProgramName(L"android_python"); #if PY_MAJOR_VERSION >= 3 /* our logging module for android */ PyImport_AppendInittab("androidembed", initandroidembed); #endif LOG("Preparing to initialize python"); if (dir_exists("crystax_python/")) { LOG("crystax_python exists"); char paths[256]; snprintf(paths, 256, "%s/crystax_python/stdlib.zip:%s/crystax_python/modules", env_argument, env_argument); /* snprintf(paths, 256, "%s/stdlib.zip:%s/modules", env_argument, env_argument); */ LOG("calculated paths to be..."); LOG(paths); #if PY_MAJOR_VERSION >= 3 wchar_t* wchar_paths = Py_DecodeLocale(paths, NULL); Py_SetPath(wchar_paths); #else char* wchar_paths = paths; LOG("Can't Py_SetPath in python2, so crystax python2 doesn't work yet"); exit(1); #endif LOG("set wchar paths..."); } else { LOG("crystax_python does not exist");} Py_Initialize(); #if PY_MAJOR_VERSION < 3 PySys_SetArgv(argc, argv); #endif LOG("Initialized python"); /* ensure threads will work. */ LOG("AND: Init threads"); PyEval_InitThreads(); #if PY_MAJOR_VERSION < 3 initandroidembed(); #endif PyRun_SimpleString("import androidembed\nandroidembed.log('testing python print redirection')"); /* inject our bootstrap code to redirect python stdin/stdout * replace sys.path with our path */ PyRun_SimpleString("import sys, posix\n"); if (dir_exists("lib")) { /* If we built our own python, set up the paths correctly */ LOG("Setting up python from ANDROID_PRIVATE"); PyRun_SimpleString( "private = posix.environ['ANDROID_PRIVATE']\n" \ "argument = posix.environ['ANDROID_ARGUMENT']\n" \ "sys.path[:] = [ \n" \ " private + '/lib/python27.zip', \n" \ " private + '/lib/python2.7/', \n" \ " private + '/lib/python2.7/lib-dynload/', \n" \ " private + '/lib/python2.7/site-packages/', \n" \ " argument ]\n"); } if (dir_exists("crystax_python")) { char add_site_packages_dir[256]; snprintf(add_site_packages_dir, 256, "sys.path.append('%s/crystax_python/site-packages')", env_argument); PyRun_SimpleString( "import sys\n" \ "sys.argv = ['notaninterpreterreally']\n" \ "from os.path import realpath, join, dirname"); PyRun_SimpleString(add_site_packages_dir); /* "sys.path.append(join(dirname(realpath(__file__)), 'site-packages'))") */ PyRun_SimpleString("sys.path = ['.'] + sys.path"); } PyRun_SimpleString( "class LogFile(object):\n" \ " def __init__(self):\n" \ " self.buffer = ''\n" \ " def write(self, s):\n" \ " s = self.buffer + s\n" \ " lines = s.split(\"\\n\")\n" \ " for l in lines[:-1]:\n" \ " androidembed.log(l)\n" \ " self.buffer = lines[-1]\n" \ " def flush(self):\n" \ " return\n" \ "sys.stdout = sys.stderr = LogFile()\n" \ "print('Android path', sys.path)\n" \ "import os\n" \ "print('os.environ is', os.environ)\n" \ "print('Android kivy bootstrap done. __name__ is', __name__)"); /* PyRun_SimpleString( */ /* "import sys, posix\n" \ */ /* "private = posix.environ['ANDROID_PRIVATE']\n" \ */ /* "argument = posix.environ['ANDROID_ARGUMENT']\n" \ */ /* "sys.path[:] = [ \n" \ */ /* " private + '/lib/python27.zip', \n" \ */ /* " private + '/lib/python2.7/', \n" \ */ /* " private + '/lib/python2.7/lib-dynload/', \n" \ */ /* " private + '/lib/python2.7/site-packages/', \n" \ */ /* " argument ]\n" \ */ /* "import androidembed\n" \ */ /* "class LogFile(object):\n" \ */ /* " def __init__(self):\n" \ */ /* " self.buffer = ''\n" \ */ /* " def write(self, s):\n" \ */ /* " s = self.buffer + s\n" \ */ /* " lines = s.split(\"\\n\")\n" \ */ /* " for l in lines[:-1]:\n" \ */ /* " androidembed.log(l)\n" \ */ /* " self.buffer = lines[-1]\n" \ */ /* " def flush(self):\n" \ */ /* " return\n" \ */ /* "sys.stdout = sys.stderr = LogFile()\n" \ */ /* "import site; print site.getsitepackages()\n"\ */ /* "print 'Android path', sys.path\n" \ */ /* "print 'Android kivy bootstrap done. __name__ is', __name__"); */ LOG("AND: Ran string"); /* run it ! */ LOG("Run user program, change dir and execute main.py"); /* search the initial main.py */ char *main_py = "main.pyo"; if ( file_exists(main_py) == 0 ) { if ( file_exists("main.py") ) main_py = "main.py"; else main_py = NULL; } if ( main_py == NULL ) { LOG("No main.pyo / main.py found."); return -1; } fd = fopen(main_py, "r"); if ( fd == NULL ) { LOG("Open the main.py(o) failed"); return -1; } /* run python ! */ ret = PyRun_SimpleFile(fd, main_py); if (PyErr_Occurred() != NULL) { ret = 1; PyErr_Print(); /* This exits with the right code if SystemExit. */ PyObject *f = PySys_GetObject("stdout"); if (PyFile_WriteString("\n", f)) /* python2 used Py_FlushLine, but this no longer exists */ PyErr_Clear(); } /* close everything */ Py_Finalize(); fclose(fd); LOG("Python for android ended."); return ret; }