Repository: kivy/python-for-android

Issue:
ctypes.util.find_library 64-bit error
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

```python
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:

```python
# 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()
```

```ini
# 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](../blob/develop/pythonforandroid/recipes/android/src/android/_ctypes_library_finder.py#L47). 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.


Discussion:

Resolving patch:
diff --git a/pythonforandroid/recipes/android/src/android/_ctypes_library_finder.py b/pythonforandroid/recipes/android/src/android/_ctypes_library_finder.py
--- a/pythonforandroid/recipes/android/src/android/_ctypes_library_finder.py
+++ b/pythonforandroid/recipes/android/src/android/_ctypes_library_finder.py
@@ -1,4 +1,5 @@
 
+import sys
 import os
 
 
@@ -44,7 +45,10 @@ def does_libname_match_filename(search_name, file_path):
 
 def find_library(name):
     # Obtain all places for native libraries:
-    lib_search_dirs = ["/system/lib"]
+    if sys.maxsize > 2**32:  # 64bit-build
+        lib_search_dirs = ["/system/lib64", "/system/lib"]
+    else:
+        lib_search_dirs = ["/system/lib"]
     lib_dir_1 = get_activity_lib_dir("org.kivy.android.PythonActivity")
     if lib_dir_1 is not None:
         lib_search_dirs.insert(0, lib_dir_1)


Test patch: