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,90 @@ 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 )) {
173+
174+ #if PY_MAJOR_VERSION >= 3
175+
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" );
182+ #endif
183+
184+ #else
185+ Py_SetProgramName ("android_python" );
186+ #endif
187+
188+ if (dir_exists (python_bundle_dir )) {
178189 LOGP ("_python_bundle dir exists" );
179- snprintf (paths , 256 ,
180- "%s/stdlib.zip:%s/modules" ,
181- python_bundle_dir , python_bundle_dir );
182190
183- LOGP ( "calculated paths to be..." ) ;
184- LOGP ( paths ) ;
191+ wchar_t wchar_zip_path [ 256 ] ;
192+ wchar_t wchar_modules_path [ 256 ] ;
185193
186- #if PY_MAJOR_VERSION >= 3
194+ swprintf (wchar_zip_path , 256 , L"%s/stdlib.zip" , python_bundle_dir );
195+ swprintf (wchar_modules_path , 256 , L"%s/modules" , python_bundle_dir );
196+
197+ LOGP ("Appending module search paths:" );
198+
199+ #if PY_MAJOR_VERSION >= 3
200+ #if PY_MINOR_VERSION >= P4A_MIN_VER
201+ config .module_search_paths_set = 1 ;
202+ PyWideStringList_Append (& config .module_search_paths , wchar_zip_path );
203+ PyWideStringList_Append (& config .module_search_paths , wchar_modules_path );
204+ LOGP ("YES FUCKER 1" );
205+ #else
206+ char paths [512 ];
207+ snprintf (paths , 512 , "%s/stdlib.zip:%s/modules" , python_bundle_dir , python_bundle_dir );
187208 wchar_t * wchar_paths = Py_DecodeLocale (paths , NULL );
188209 Py_SetPath (wchar_paths );
189210 #endif
211+ #endif
212+
213+ LOGP ("set wchar paths..." );
214+ } else {
215+ LOGP ("_python_bundle does not exist...this not looks good, all python"
216+ " recipes should have this folder, should we expect a crash soon?" );
217+ }
218+
219+ #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= P4A_MIN_VER
220+ PyStatus status = Py_InitializeFromConfig (& config );
221+ if (PyStatus_Exception (status )) {
222+ LOGP ("Python initialization failed: %s" );
223+ LOGP (status .err_msg );
224+ Py_ExitStatusException (status ); // this will exit the program with error
225+ } else {
226+ LOGP ("Python initialized successfully using Py_InitializeFromConfig." );
227+ }
228+ #else
229+ Py_Initialize ();
230+ LOGP ("Python initialized using legacy Py_Initialize()." );
231+ #endif
190232
191- LOGP ("set wchar paths..." );
192- } 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?" );
195- }
196233
197- Py_Initialize ();
198234 LOGP ("Initialized python" );
199235
200- /* ensure threads will work.
201- */
202- LOGP ("AND: Init threads" );
203- PyEval_InitThreads ();
236+ /* < 3.9 requires explicit GIL initialization
237+ * 3.9+ PyEval_InitThreads() is deprecated and unnecessary
238+ */
239+ #if PY_VERSION_HEX < 0x03090000
240+ LOGP ("Initializing threads (required for Python < 3.9)" );
241+ PyEval_InitThreads ();
242+ #endif
204243
205244#if PY_MAJOR_VERSION < 3
206245 initandroidembed ();
207246#endif
208247
209- PyRun_SimpleString ("import androidembed\nandroidembed.log('testing python "
210- "print redirection')" );
248+ PyRun_SimpleString (
249+ "import sys;print(sys.path)"
250+ );
251+
252+ PyRun_SimpleString (
253+ "import androidembed\n"
254+ "androidembed.log('testing python print redirection')"
255+
256+ );
211257
212258 /* inject our bootstrap code to redirect python stdin/stdout
213259 * replace sys.path with our path
@@ -325,20 +371,6 @@ int main(int argc, char *argv[]) {
325371
326372 LOGP ("Python for android ended." );
327373
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 );
342374
343375 /* This should never actually be reached, but we'll leave the clean-up
344376 * here just to be safe.
0 commit comments