英文:
Problem with .a library implementation using Android NDK. Functions throw undefined symbol error
问题
I understand that you'd like a translation of the code and error message provided. Here is the translated code snippet:
#include <jni.h>
#include "es_rgil.h"
extern "C" JNIEXPORT int32_t JNICALL
Java_com_bartosz_lewandowski_libraryconnector_MainActivity_mifareAuth(JNIEnv *env,
jobject /* this */,
jbyte sector,
jboolean keyType,
jbyte key,
jsize len) {
es_rgil_mifare_key_type k_type = ES_RGIL_MIFARE_KEY_A;
if (keyType) {
k_type = ES_RGIL_MIFARE_KEY_B;
}
return es_rgil_mifare_auth(static_cast<uint8_t>(sector), k_type, reinterpret_cast<const uint8_t*>(key), len);
}
Your CMakeLists.txt file remains the same, and the error message you provided indicates an "undefined symbol" error, which means the linker can't find the es_rgil_mifare_auth
function. Ensure that your library (libes_rgil.a
) is correctly linked and contains the necessary symbols.
If you have any specific questions or need further assistance, please let me know.
英文:
I'm completely new to NDK (and C/C++) so I'm sorry if the question may be too elemental. I have a problem thrying to import to my Android Kotlin project a library written in C.
I'm not sure if the problem is in my CmakeLists file or in trying to convert C variable types to JNI or JNI to Kotlin. Or I'm doing something wrong with linking header with .a file? I have a header file named es_rgil.h and a static library librgil.a. Android Studio sees this library becouse it suggested to create functions colors my code in every file.
I'll be very grateful for any advice or solution. I'm strugeling with this for a week and getting crazy...
In the header there is a function which looks like: int32_t es_rgil_mifare_auth(const uint8_t sector, const es_rgil_mifare_key_type key_type, const uint8_t *key, const size_t key_size);
My native-lib.cpp file which is my bridge between C and kotlin looks like this:
#include <jni.h>
#include "es_rgil.h"
extern "C" JNIEXPORT int32_t JNICALL
Java_com_bartosz_lewandowski_libraryconnector_MainActivity_mifareAuth(JNIEnv *env,
jobject /* this */,
jbyte sector,
jboolean keyType,
jbyte key,
jsize len) {
es_rgil_mifare_key_type k_type = ES_RGIL_MIFARE_KEY_A;
if (keyType) {
k_type = ES_RGIL_MIFARE_KEY_B;
}
return es_rgil_mifare_auth((uint8_t )sector, k_type, reinterpret_cast<const uint8_t *>(key), len);
}
In my activity file export function looks like: external fun mifareAuth(sector: Byte, isKeyTypeB: Boolean, key: Byte, len: Int): Int
CMakeLists looks like this:
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.22.1)
# Declares and names the project.
project(libraryconnector)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library(
es_rgil
STATIC
es_rgil.h
)
add_library( # Sets the name of the library.
libraryconnector
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
#find_library( # Sets the name of the path variable.
# log-lib
#
# # Specifies the name of the NDK library that
# # you want CMake to locate.
# log)
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
set_target_properties(es_rgil PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries( # Specifies the target library.
libraryconnector
es_rgil)
# Links the target library to the log library
# included in the NDK.
# ${log-lib})
Error:
cmd.exe /C "cd . && D:\AndroidSDK\ndk.1.8937393\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android24 --sysroot=D:/AndroidSDK/ndk/25.1.8937393/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -std=c++11 -fno-limit-debug-info -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--fatal-warnings -Wl,--gc-sections -Wl,--no-undefined -Qunused-arguments -shared -Wl,-soname,liblibraryconnector.so -o C:\Users\barte\AndroidStudioProjects\LibraryConnector\app\build\intermediates\cxx\Debug4i55q5\obj\arm64-v8a\liblibraryconnector.so CMakeFiles/libraryconnector.dir/native-lib.cpp.o libes_rgil.a -latomic -lm && cd ."
ld: error: undefined symbol: es_rgil_mifare_auth
>>> referenced by native-lib.cpp:26 (C:/Users/barte/AndroidStudioProjects/LibraryConnector/app/src/main/cpp/native-lib.cpp:26)
>>> CMakeFiles/libraryconnector.dir/native-lib.cpp.o:(Java_com_bartosz_lewandowski_libraryconnector_MainActivity_mifareAuth)
cmd.exe /C "cd . && D:\AndroidSDK\ndk.1.8937393\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android24 --sysroot=D:/AndroidSDK/ndk/25.1.8937393/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -std=c++11 -fno-limit-debug-info -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--fatal-warnings -Wl,--gc-sections -Wl,--no-undefined -Qunused-arguments -shared -Wl,-soname,liblibraryconnector.so -o C:\Users\barte\AndroidStudioProjects\LibraryConnector\app\build\intermediates\cxx\Debug4i55q5\obj\arm64-v8a\liblibraryconnector.so CMakeFiles/libraryconnector.dir/native-lib.cpp.o libes_rgil.a -latomic -lm && cd ."
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
I tried different combinations of variable types, different aproaches to write CMakeLists file.
答案1
得分: 0
你正在寻找的概念是一个导入目标:
add_library(es_rgil STATIC IMPORTED)
set_property(TARGET es_rgil PROPERTY IMPORTED_LOCATION "librgil.a")
第二行告诉CMake实际的代码在哪里,以及它应该如何被合并到你的主目标库中。
你还可以选择使用 target_include_directories
来告诉CMake头文件位于哪里,就像这样:
target_include_directories(es_rgil INTERFACE some/subdir/rgil)
英文:
The concept you are looking for is an IMPORTED target:
add_library(es_rgil STATIC IMPORTED)
set_property(TARGET es_rgil PROPERTY IMPORTED_LOCATION "librgil.a")
The second line tells CMake where the actual code is and how it should be incorporated into your main target's library.
You can optionally use target_include_directories
to tell CMake where the header file lives like so:
target_include_directories(es_rgil INTERFACE some/subdir/rgil)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论