3131#define ENTRYPOINT_MAXLEN 128
3232#define LOG (n , x ) __android_log_write(ANDROID_LOG_INFO, (n), (x))
3333#define LOGP (x ) LOG("python", (x))
34+ #define P4A_MIN_VER 11
3435
3536static PyObject * androidembed_log (PyObject * self , PyObject * args ) {
3637 char * logstr = NULL ;
@@ -154,11 +155,6 @@ int main(int argc, char *argv[]) {
154155 Py_NoSiteFlag = 1 ;
155156#endif
156157
157- #if PY_MAJOR_VERSION < 3
158- Py_SetProgramName ("android_python" );
159- #else
160- Py_SetProgramName (L"android_python" );
161- #endif
162158
163159#if PY_MAJOR_VERSION >= 3
164160 /* our logging module for android
@@ -174,40 +170,80 @@ int main(int argc, char *argv[]) {
174170 char python_bundle_dir [256 ];
175171 snprintf (python_bundle_dir , 256 ,
176172 "%s/_python_bundle" , getenv ("ANDROID_UNPACK" ));
177- if (dir_exists (python_bundle_dir )) {
178- LOGP ("_python_bundle dir exists" );
179- snprintf (paths , 256 ,
180- "%s/stdlib.zip:%s/modules" ,
181- python_bundle_dir , python_bundle_dir );
182173
183- LOGP ("calculated paths to be..." );
184- LOGP (paths );
174+ #if PY_MAJOR_VERSION >= 3
185175
186- #if PY_MAJOR_VERSION >= 3
187- wchar_t * wchar_paths = Py_DecodeLocale (paths , NULL );
188- Py_SetPath (wchar_paths );
176+ #if PY_MINOR_VERSION >= P4A_MIN_VER
177+ PyConfig config ;
178+ PyConfig_InitPythonConfig (& config );
179+ config .program_name = L"android_python" ;
180+ #else
181+ Py_SetProgramName (L"android_python" );
189182 #endif
190183
191- LOGP ("set wchar paths..." );
184+ #else
185+ Py_SetProgramName ("android_python" );
186+ #endif
187+
188+ if (dir_exists (python_bundle_dir )) {
189+ LOGP ("_python_bundle dir exists" );
190+
191+ #if PY_MAJOR_VERSION >= 3
192+ #if PY_MINOR_VERSION >= P4A_MIN_VER
193+
194+ wchar_t wchar_zip_path [256 ];
195+ wchar_t wchar_modules_path [256 ];
196+ swprintf (wchar_zip_path , 256 , L"%s/stdlib.zip" , python_bundle_dir );
197+ swprintf (wchar_modules_path , 256 , L"%s/modules" , python_bundle_dir );
198+
199+ config .module_search_paths_set = 1 ;
200+ PyWideStringList_Append (& config .module_search_paths , wchar_zip_path );
201+ PyWideStringList_Append (& config .module_search_paths , wchar_modules_path );
202+ #else
203+ char paths [512 ];
204+ snprintf (paths , 512 , "%s/stdlib.zip:%s/modules" , python_bundle_dir , python_bundle_dir );
205+ wchar_t * wchar_paths = Py_DecodeLocale (paths , NULL );
206+ Py_SetPath (wchar_paths );
207+ #endif
208+
209+ #endif
210+
211+ LOGP ("set wchar paths..." );
192212 } else {
193- LOGP ("_python_bundle does not exist...this not looks good, all python"
194- " recipes should have this folder, should we expect a crash soon?" );
213+ LOGP ("_python_bundle does not exist...this not looks good, all python"
214+ " recipes should have this folder, should we expect a crash soon?" );
195215 }
196216
197- Py_Initialize ();
217+ #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= P4A_MIN_VER
218+ PyStatus status = Py_InitializeFromConfig (& config );
219+ if (PyStatus_Exception (status )) {
220+ LOGP ("Python initialization failed:" );
221+ LOGP (status .err_msg );
222+ }
223+ #else
224+ Py_Initialize ();
225+ LOGP ("Python initialized using legacy Py_Initialize()." );
226+ #endif
227+
198228 LOGP ("Initialized python" );
199229
200- /* ensure threads will work.
201- */
202- LOGP ("AND: Init threads" );
203- PyEval_InitThreads ();
230+ /* < 3.9 requires explicit GIL initialization
231+ * 3.9+ PyEval_InitThreads() is deprecated and unnecessary
232+ */
233+ #if PY_VERSION_HEX < 0x03090000
234+ LOGP ("Initializing threads (required for Python < 3.9)" );
235+ PyEval_InitThreads ();
236+ #endif
204237
205238#if PY_MAJOR_VERSION < 3
206239 initandroidembed ();
207240#endif
208241
209- PyRun_SimpleString ("import androidembed\nandroidembed.log('testing python "
210- "print redirection')" );
242+ PyRun_SimpleString (
243+ "import androidembed\n"
244+ "androidembed.log('testing python print redirection')"
245+
246+ );
211247
212248 /* inject our bootstrap code to redirect python stdin/stdout
213249 * replace sys.path with our path
@@ -325,20 +361,6 @@ int main(int argc, char *argv[]) {
325361
326362 LOGP ("Python for android ended." );
327363
328- /* Shut down: since regular shutdown causes issues sometimes
329- (seems to be an incomplete shutdown breaking next launch)
330- we'll use sys.exit(ret) to shutdown, since that one works.
331-
332- Reference discussion:
333-
334- https://github.com/kivy/kivy/pull/6107#issue-246120816
335- */
336- char terminatecmd [256 ];
337- snprintf (
338- terminatecmd , sizeof (terminatecmd ),
339- "import sys; sys.exit(%d)\n" , ret
340- );
341- PyRun_SimpleString (terminatecmd );
342364
343365 /* This should never actually be reached, but we'll leave the clean-up
344366 * here just to be safe.
0 commit comments