gpt4 book ai didi

Android:如何从 JNI 代码中使用现有的 C++ 静态库?

转载 作者:太空狗 更新时间:2023-10-29 16:07:15 27 4
gpt4 key购买 nike

我见过类似的问题,但场景并不完全相同,也找不到适合我问题的答案。

我有一个 C++ 库的源代码。我们需要将该库用作 android 应用程序的一部分,但它也需要可供第三方用作 C++ 库。

我有一个 makefile,它使用 ndk 的编译器从库的源代码中生成 .a 文件。那是纯 C++ 部分。

在 Java 部分,我有一个简单的演示项目,其中包含一个包含按钮的简单 Activity 。按下按钮时,将调用 native 代码。

只要我不尝试从 JNI 函数调用库中的函数,一切正常。

这里是图书馆的来源:

SimpleMath.h

int Add(int aNumber1, int aNumberB);

SimpleMath.cpp

#include "SimpleMath.h"

int Add(int aNumberA, int aNumberB)
{
return aNumberA + aNumberB;
}

生成文件

APP      = simple_app
LIBRARY = simple_library.a
OBJECTS = SimpleMath.o
CFLAGS = -Wall -pedantic
NDK_PATH = /home/jug/perforce/jug_navui_personal_main/Env/Linux/Android/ndk/r7c
CXX = $(NDK_PATH)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-g++
AR = $(NDK_PATH)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-ar
SYSTEM_LIBS = -lstdc++ -lm
INCLUDE_PATH += ${NDK_PATH}/platforms/android-9/arch-arm/usr/include

all: $(LIBRARY)

$(LIBRARY):
$(CXX) -c SimpleMath.c
$(AR) rcs simple_library.a SimpleMath.o

clean:
rm *.o *.a

在 java 端,这些是文件:

你好-jni.c

#include <string.h>
#include <jni.h>

#include "../../../native/simple_library/SimpleMath.h"

jstring Java_com_amstapps_samples_draft08jni_MainActivity_helloJni(JNIEnv* env, jobject obj)
{
// Uncommenting the line below results in undefined-symbol compile error
//int d = Add(1, 2);

return (*env)->NewStringUTF(env, "Hello from JNI!");
}

Android.mk

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := my_simple_library
LOCAL_ARM_MODE := arm
LOCAL_SRC_FILES := ../../../native/simple_library/simple_library.a
include $(PREBUILT_STATIC_LIBRARY)
#include $(BUILD_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := eng
LOCAL_ARM_MODE := arm
#LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
LOCAL_C_INCLUDES := ../../../android/native/simple_library
LOCAL_STATIC_LIBRARIES := my_simple_library
#LOCAL_WHOLE_STATIC_LIBRARIES := my_simple_library
include $(BUILD_SHARED_LIBRARY)

Application.mk

APP_MODULES := my_simple_library hello-jni

正如我所说,当我实际使用 java 应用程序中的 jni native 代码库中的功能时,问题就来了。

现在,我不再确定我的问题是在静态库的 makefile 中还是在 Android.mk 中。我最初认为这一定与库本身的生成有关,但在这一点上,在看到 Android.mk 中有这么多我不知道的选项后,我不得不承认我不知道。

还有什么……?

哦,是的,我还注意到我的纯 C++ 库使用的是 cpp 扩展,而 java 项目中的 jni 代码使用的是 c 扩展。我试图让后者也使用 cpp,但编译器提示。这可能是问题的一部分吗?

我在尝试编译 Android.mk 文件时得到的错误代码是“ undefined symbol ”,因此,simple_library.a 中的函数列表(实际上有 1 个函数)对 hello-jni.c 不可见,因为它是 C++ 而不是普通的 C?

您可能会注意到的另一件事是,我尝试在其自己的 makefile 上构建静态库,而不是使用 Android.mk 生成它;这是有原因的,但在这一点上,如果我必须让 Android.mk 生成它,如果需要的话,我也会很高兴。

我看不出有什么方法可以在这里添加附件以便与项目共享 zip。如果我遗漏了什么,请告诉我。否则代码在 bitbucket 的仓库中,因此我可以轻松地与在那里也有帐户的任何人共享它。

感谢您的回答。

最佳答案

你写了很多正确的东西,但你只漏了一个。

该函数的名称在 C++ 中被破坏了。在 .so 文件中你没有得到“Add”符号,而是类似“Add@8i”的东西。为避免损坏,只需使用

extern "C" int Add(int x, int y)

.cpp 文件和 .h 中的声明

通常还会添加

/// Some .h file
#ifdef __cplusplus
extern "C" {
#endif

/// Your usual C-like declarations go here

#ifdef __cplusplus
} // extern "C"
#endif

extern "C"

对于 .cpp 文件中的每个导出函数。

关于Android:如何从 JNI 代码中使用现有的 C++ 静态库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11348646/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com