我想在我的Android应用程序中包含两个共享库liba.so
和libb.so
。从libb.so
中的函数中调用liba.so
的函数。
我有一个Java类,它调用本地JNI函数为
package com.test.myapplication;
public class MainActivity extends AppCompatActivity {
static{
System.loadLibrary(a);
System.loadLibrary(b);
}
public native void testSample();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testSample();
}
}
我的JNI文件是
#include"a.h"
extern "C" void JNICALL Java_com_test_myapplication_MainActivity_testSample( JNIEnv* env, jobject thiz) {
a_foo();
}
属于我的库liba.so的a.cpp文件是
#include"b.h"
void a_foo()
{
/* ..... code .....*/
b_foo();
/* ..... code .....*/
}
我的b.cpp是libb.so的一部分
void b_foo()
{
/* ..... code .....*/
}
我想将liba.so和libb.so作为librares而不是作为源添加到我的应用程序中。这两个库都是使用android-ndk独立构建的。
答案 0 :(得分:0)
我将假设您已经掌握了Java / Android部分,因为自从我完成任何Java或Android以来已经有很多年了(甚至在那时还处于大学水平)。如果您不这样做,我只是读了一篇有关JNI的short post,使我对使Java代码正常工作实际需要做的事情有一个大致的了解。
您需要从JNI源代码构建新的库,并使用 System.loadLibrary()调用从Java源中加载该库。现在我们称其为 libjni.so 。
在CMake中,您可以通过以下方式进行操作:
# jni.c is the file containing the **testSample** function with call to **a_foo()**
add_library(jni SHARED jni.c)
target_link_libraries(jni PRIVATE liba)
这将为您创建一个 libjni.so 文件,该文件将链接到 liba.so 。您可以像这样从Java文件加载该文件:
System.loadLibrary(jni);
如果 liba.so 不是从同一CMake项目构建的,则需要*使用CMake的find_library和add_library将其导入为目标。在线和CMake 查找模块中都有大量示例。构建它时,它应该已经指定了它的依赖关系(即,如果您执行ldd liba.so
,它应该说它链接到 libb.so )。如果没有,您也无法自己解决此问题,则可以将 libb.so 导入为另一个目标,并将其附加到上面的 target_link_library 行中。
这足以让您处理Java / Android代码正常工作所需的共享对象文件,再次假设可以实现将所有Java / Android位放到CMake中的过程。
*实际上,您可以在 target_link_libraries 调用中使用库的完整路径,但是根据“现代CMake”技术,这并不是很习惯。
编辑
但是我应该如何将libb链接到liba
谁构建 liba 和 libb ?
它们是您维护的单独项目的来源吗?如果是这样,则需要更改您的 liba 构建系统,使其链接到 libb 。然后重建 liba ,您的JNI lib和问题将消失。
如果您自己不维护它们,则需要:
a)导入 libb.so 的方式与导入 liba.so 的方式相同({find_library
,后跟add_library
-上面的链接),然后使用set_target_properties
b)引起 liba.so 的维护者的问题-如果一个库使用另一个库,则维护者的工作就是满足这种依赖性,而不是用户。