如何在 android 应用程序中的 cmake 中使用两个预构建的相互依赖的共享库
How to use two prebuilt interdependent shared libraries in cmake in android Application
我想在我的 android 应用程序中包含两个共享库 liba.so
和 libb.so
。其中 libb.so
的函数是从 liba.so
中的函数调用的。
我有一个 Java class 调用本机 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();
}
a.cpp 属于我的库 liba.so 的文件是
#include"b.h"
void a_foo()
{
/* ..... code .....*/
b_foo();
/* ..... code .....*/
}
我的 b.cpp 是 libb.so 的一部分
void b_foo()
{
/* ..... code .....*/
}
我想将 liba.so 和 libb.so 作为库而不是源包含在我的应用程序中。这两个库都是使用 android-ndk 独立构建的。
我假设你已经弄清楚了 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 文件,它将 link 到 liba.so.您可以像这样从 Java 文件加载它:
System.loadLibrary(jni);
如果 liba.so 不是从同一个 CMake 项目构建的,您需要*使用 CMake 的 find_library and add_library 将其作为目标导入。在线和 CMake Find 模块中有大量示例。当它被构建时,它应该已经指定了它的依赖关系(即如果你做 ldd liba.so
它应该说它 links 到 libb.so) .如果没有,并且您自己无法解决此问题,则可以导入 libb.so 作为另一个目标并将其附加到 target_link_library 行以上。
这应该足以让您使用 Java/Android 代码工作所需的共享对象文件,再次假设在 CMake 中将所有 Java/Android 位放在一起的过程可以be/has 已实现。
* 您实际上可以在 target_link_libraries 调用中使用库的完整路径,但根据 "Modern CMake" 技术,这不是很惯用。
编辑
But how should I link libb to liba
谁构建了 liba 和 libb?
它们是您维护的独立项目的来源吗?如果是这样,您需要更改 liba 构建系统,使其 link 变为 libb。然后重建 liba 和你的 JNI 库,你的问题就会消失。
如果您不自己维护它们,则需要:
a) 以相同的方式导入 libb.so liba.so (find_library
随后通过 add_library
- links 以上),然后改变 liba.so 的目标,使 libb.so 目标作为 link 依赖使用 set_target_properties
b) 向 liba.so 的维护者提出问题 - 如果一个库使用另一个库,则维护者的工作是满足这种依赖性,而不是用户。
我想在我的 android 应用程序中包含两个共享库 liba.so
和 libb.so
。其中 libb.so
的函数是从 liba.so
中的函数调用的。
我有一个 Java class 调用本机 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();
}
a.cpp 属于我的库 liba.so 的文件是
#include"b.h"
void a_foo()
{
/* ..... code .....*/
b_foo();
/* ..... code .....*/
}
我的 b.cpp 是 libb.so 的一部分
void b_foo()
{
/* ..... code .....*/
}
我想将 liba.so 和 libb.so 作为库而不是源包含在我的应用程序中。这两个库都是使用 android-ndk 独立构建的。
我假设你已经弄清楚了 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 文件,它将 link 到 liba.so.您可以像这样从 Java 文件加载它:
System.loadLibrary(jni);
如果 liba.so 不是从同一个 CMake 项目构建的,您需要*使用 CMake 的 find_library and add_library 将其作为目标导入。在线和 CMake Find 模块中有大量示例。当它被构建时,它应该已经指定了它的依赖关系(即如果你做 ldd liba.so
它应该说它 links 到 libb.so) .如果没有,并且您自己无法解决此问题,则可以导入 libb.so 作为另一个目标并将其附加到 target_link_library 行以上。
这应该足以让您使用 Java/Android 代码工作所需的共享对象文件,再次假设在 CMake 中将所有 Java/Android 位放在一起的过程可以be/has 已实现。
* 您实际上可以在 target_link_libraries 调用中使用库的完整路径,但根据 "Modern CMake" 技术,这不是很惯用。
编辑
But how should I link libb to liba
谁构建了 liba 和 libb?
它们是您维护的独立项目的来源吗?如果是这样,您需要更改 liba 构建系统,使其 link 变为 libb。然后重建 liba 和你的 JNI 库,你的问题就会消失。
如果您不自己维护它们,则需要:
a) 以相同的方式导入 libb.so liba.so (find_library
随后通过 add_library
- links 以上),然后改变 liba.so 的目标,使 libb.so 目标作为 link 依赖使用 set_target_properties
b) 向 liba.so 的维护者提出问题 - 如果一个库使用另一个库,则维护者的工作是满足这种依赖性,而不是用户。