Ten dokument zawiera częściową listę najczęstszych błędów, które mogą wystąpić podczas korzystania z pakietu NDK, wraz z ich rozwiązaniami (jeśli są dostępne).
Używanie _FILE_OFFSET_BITS=64
ze starszymi poziomami API
Przed ujednoliconymi nagłówkami pakiet NDK nie obsługiwał _FILE_OFFSET_BITS=64
. Jeśli określisz ją podczas tworzenia aplikacji, zostanie ona dyskretnie zignorowana. Opcja _FILE_OFFSET_BITS=64
jest teraz obsługiwana z ujednoliconymi nagłówkami, ale w starszych wersjach Androida bardzo niewiele interfejsów API off_t
było dostępnych jako wariant off64_t
. Dlatego użycie tej funkcji na starszych poziomach API zmniejsza liczbę dostępnych funkcji.
Szczegółowo wyjaśniliśmy ten problem w poście na blogu R16 i w dokumentacji systemu Bionic.
Problem: kompilacja prosi o interfejsy API, których nie ma w minSdkVersion
.
Rozwiązanie: wyłącz _FILE_OFFSET_BITS=64
lub zwiększ minSdkVersion
.
Niezadeklarowana lub niejawna definicja słowa mmap
W C++ może pojawić się taki błąd:
błąd: użycie niezadeklarowanego identyfikatora „mmap”
lub następujący błąd w C:
ostrzeżenie: niejawna deklaracja funkcji „mmap” jest nieprawidłowa w C99
Użycie właściwości _FILE_OFFSET_BITS=64
powoduje, że biblioteka C używa właściwości mmap64
zamiast mmap
. Usługa mmap64
była niedostępna do android-21
. Jeśli wartość minSdkVersion
jest mniejsza niż 21, biblioteka C nie zawiera elementu mmap
zgodnej z _FILE_OFFSET_BITS=64
, więc funkcja jest niedostępna.
Element minSdkVersion
jest ustawiony wyżej niż poziom interfejsu API urządzenia
Poziom interfejsu API, do którego odnosi się pakiet NDK, ma zupełnie inne znaczenie niż compileSdkVersion
w Javie. Poziom interfejsu NDK API to minimalny obsługiwany poziom interfejsu API aplikacji. W ndk-build to jest Twoje ustawienie APP_PLATFORM
. W CMake jest to -DANDROID_PLATFORM
.
Odniesienia do funkcji są zwykle rozpoznawane podczas wczytywania bibliotek, a nie przy ich pierwszym wywołaniu, dlatego nie możesz odwoływać się do interfejsów API, które nie zawsze są dostępne, i kontrolować ich użycie za pomocą kontroli na poziomie interfejsu API. Jeśli w ogóle się do nich odwołujesz, muszą być obecni.
Problem: poziom interfejsu NDK API jest wyższy niż interfejs API obsługiwany przez Twoje urządzenie.
Rozwiązanie: ustaw poziom interfejsu NDK API (APP_PLATFORM
) na minimalną wersję Androida obsługiwaną przez Twoją aplikację.
System kompilacji | Ustawienie |
---|---|
ndk-build | APP_PLATFORM |
Tworzenie środowiska wykonawczego | ANDROID_PLATFORM |
externalNativeBuild | android.minSdkVersion |
W przypadku innych systemów kompilacji przeczytaj artykuł o używaniu pakietu NDK z innymi systemami kompilacji.
Nie można znaleźć symboli __aeabi
Następująca wiadomość:
UnsatisfiedLinkError: dlopen Błąd: nie można znaleźć symbolu „
__aeabi_memcpy
”
to jeden z przykładów możliwych błędów w środowisku wykonawczym. Te błędy pojawiają się w dzienniku, gdy próbujesz wczytać swoje biblioteki natywne. Może to być dowolny z tych symboli: __aeabi_*
. __aeabi_memcpy
i __aeabi_memclr
są najpopularniejsze.
Ten problem jest opisany w numerze 126
Nie można znaleźć symbolu rand
Dla tego komunikatu w dzienniku błędów:
UnsatisfiedLinkError: dlopen Błąd: nie można znaleźć symbolu „
rand
”
Zapoznaj się ze szczegółową odpowiedzią w usłudze Stack Overflow.
Niezdefiniowane odwołanie do: __atomic_*
Problem: niektóre interfejsy ABI wymagają libatomic
do udostępnienia implementacji niepodzielnych operacji.
Rozwiązanie: podczas łączenia dodaj atrybut -latomic
.
W przypadku tego komunikatu o błędzie:
błąd: niezdefiniowane odniesienie do atrybutu „
__atomic_exchange_4
”
faktycznym symbolem w tym miejscu może być dowolny element z prefiksem __atomic_
.
RTTI/wyjątki nie działają poza granicami bibliotek
Problem: wyjątki nie są wykrywane w przypadku zgłaszania ich poza granicami biblioteki udostępnionej lub usługa dynamic_cast
nie działa.
Rozwiązanie: dodaj do typów funkcję kluczową. Funkcja kluczowa to pierwsza nieczysta, pozawierszowa funkcja wirtualna danego typu. Oto przykład w dyskusji na temat numeru 533.
Interfejs C++ ABI stwierdza, że 2 obiekty są tego samego typu tylko wtedy, gdy ich wskaźniki type_info
są identyczne. Wyjątki mogą być przechwytywane tylko wtedy, gdy element type_info
dla webhooka jest zgodny z zgłoszonym wyjątkiem. Ta sama reguła dotyczy dynamic_cast
.
Gdy typ nie ma funkcji klucza, jego typeinfo
jest emitowany jako słaby symbol, a informacje o typie dopasowania są scalane podczas wczytywania bibliotek. W przypadku dynamicznego wczytywania bibliotek po załadowaniu pliku wykonywalnego (inaczej: za pomocą dlopen
lub System.loadLibrary
), moduł ładowania może nie być w stanie scalić informacji o typach załadowanych bibliotek. W takiej sytuacji ich 2 typy nie są sobie równe.
Używanie niedopasowanych gotowych bibliotek
Korzystanie w aplikacji z gotowych bibliotek (zwykle jest to biblioteki innych firm) wymaga dodatkowej uwagi. Ogólnie pamiętaj o tych regułach:
Wynikowy minimalny poziom interfejsu API aplikacji to maksymalna liczba korzystających z funkcji
minSdkVersion
wszystkich bibliotek aplikacji.Jeśli
minSdkVersion
ma wartość 16, ale używasz gotowej biblioteki skompilowanej pod kątem wersji 21, minimalny poziom interfejsu API aplikacji to 21. Jeśli tego nie zrobisz, będzie to widoczne podczas kompilacji, jeśli gotowa biblioteka jest statyczna, ale może się pojawić dopiero w czasie wykonywania gotowych bibliotek udostępnionych.Wszystkie biblioteki powinny być generowane w tej samej wersji pakietu NDK.
Ta reguła jest trochę bardziej elastyczna niż większość większości, ponieważ awarie występują rzadko, ale zgodność między bibliotekami, które zostały utworzone z różnymi głównymi wersjami pakietu NDK, nie jest gwarantowana. Ten interfejs ABI C++ nie jest stabilny i w przeszłości zmienił się.
Aplikacje z wieloma bibliotekami udostępnionymi muszą używać udostępnionego STL.
Tak jak w przypadku niedopasowanych obrazów STL, problemów wynikających z tego problemu można uniknąć, dbając o odpowiednią ostrożność, ale lepiej po prostu unikać takich problemów. Najlepszym sposobem uniknięcia tego problemu jest unikanie posiadania w aplikacji wielu bibliotek udostępnionych.