Description
I was trying to use zeroconf
package for my application. It worked perfectly on armeabi-v7a
, however the program crashed on launch on arm64-v8a
(both tested on Huawei P30).
I have investigated the issues and discovered that the problem is with ctypes.util.find_library
or, more precisely with the p4a module andoroid._ctypes_library_finder
in the function find_library
.
The actual problem is that this function finds 32bit libraries regardless of the actual architecture. For example
ctypes.util.find_library('c')
returns /system/lib/libc.so
both for 32- and 64-bit architecture. The correct behavior is to return this if Python is compiled for 32-bit and /system/lib64/libc.so
for 64-bit one.
Below is the code of a simple Kivy app that shows the issue:
# main.py
import sys
import ctypes
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
root = Builder.load_string("""\
#:import sys sys
BoxLayout:
orientation: 'vertical'
Label:
id: arch
size_hint_y: 1
text_size: self.size
halign: 'center'
valign: 'middle'
text: '64-bit' if sys.maxsize > 2**32 else '32-bit'
Label:
id: lib
size_hint_y: 1
text_size: self.size
halign: 'center'
valign: 'middle'
Label:
id: err
size_hint_y: 4
text_size: self.size
halign: 'left'
valign: 'middle'
""")
class TestCtypesApp(App):
def build(self):
lib = ctypes.util.find_library('c')
root.ids.lib.text = str(lib)
try:
cdll = ctypes.CDLL(lib)
except Exception as err:
root.ids.err.text = "{}: {}".format(type(err).__name__, err)
else:
root.ids.err.text = 'CORRECT'
root.ids.err.halign = 'center'
return root
if __name__ == '__main__':
TestCtypesApp().run()
# buildozer.spec
[app]
title = Test CTypes
package.name = testctypes
package.domain = org.test
source.dir = .
source.include_exts = py
version = 0.1
requirements = python3,kivy
orientation = portrait
osx.python_version = 3
osx.kivy_version = 1.9.1
fullscreen = 0
android.api = 30
android.arch = armeabi-v7a
ios.kivy_ios_url = https://github.com/kivy/kivy-ios
ios.kivy_ios_branch = master
ios.ios_deploy_url = https://github.com/phonegap/ios-deploy
ios.ios_deploy_branch = 1.7.0
[buildozer]
log_level = 2
warn_on_root = 1
[app@arm64]
android.arch = arm64-v8a
When compiled for armeabi-v7a
it shows:
32-bit
/system/lib/libc.so
CORRECT
while on arm64-v8a
:
64-bit
/system/lib/libc.so
OSError: dlopen failed: library "/system/lib/libc.so" needed or dlopened by
"/data/data/org.test.testctypes/files/app/_python_bundle/modules/_ctypes.cpython-38.so"
is not accessible for this namespace "classloader-namespace"
The expected output is:
64-bit
/system/lib64/libc.so
CORRECT
The source of this problem is in the line 47 of the file pythonforandroid/recipes/android/src/android/_ctypes_library_finder.py. For 64-bit Python (build target arch matters, not the system archiecture), the libraries to search should be ["/system/lib64/libc.so", "/system/lib/libc.so"]
.
I am also submitting a pull request resolving this issue.