从 Android JNI/NDK 代码中的C++函数调用 C 函数

Calling C Functions From C++ Function In Android JNI/NDK Code

本文关键字:C++ 函数调用 函数 代码 Android JNI NDK      更新时间:2023-10-16

我正在尝试从NDKTest.c文件中调用stringFromJNI2(env,obj)函数。

以下是 NDKTest.c 文件的代码:

#include <string.h>
#include <stdio.h>
#include <jni.h>
#include <limits.h>
JNIEXPORT jstring JNICALL
Java_com_test_ndk_NDKTest_stringFromJNI2( JNIEnv *env,
jobject thiz )
{
#if defined(__arm__)
#if defined(__ARM_ARCH_7A__)
#if defined(__ARM_NEON__)
#if defined(__ARM_PCS_VFP)
#define ABI "armeabi-v7a/NEON (hard-float)"
#else
#define ABI "armeabi-v7a/NEON"
#endif
#else
#if defined(__ARM_PCS_VFP)
#define ABI "armeabi-v7a (hard-float)"
#else
#define ABI "armeabi-v7a"
#endif
#endif
#else
#define ABI "armeabi"
#endif
#elif defined(__i386__)
#define ABI "x86"
#elif defined(__x86_64__)
#define ABI "x86_64"
#elif defined(__mips64)  /* mips64el-* toolchain defines __mips__ too */
#define ABI "mips64"
#elif defined(__mips__)
#define ABI "mips"
#elif defined(__aarch64__)
#define ABI "arm64-v8a"
#else
#define ABI "unknown"
#endif
return (*env)->NewStringUTF(env, "Hello from JNI2 !  Compiled with ABI " ABI ".");
}

以下是 NDKTest.h 文件的代码:

#ifndef NDKTEST_H_
#define NDKTEST_H_
#include <jni.h>
#include <string>
const std::allocator<char> & stringFromJNI2(JNIEnv *env, jobject thiz);
#endif

以下是 TestNDK.cpp 文件的代码:

#include <string.h>
#include <jni.h>
#include <string>
#include <jni.h>
#include "NDKTest.h"
extern "C" {
stringFromJNI2(JNIEnv *env, jobject obj);
}
JNIEXPORT jstring JNICALL
Java_com_test_ndk_TestNDK_main(JNIEnv *env, jobject obj) {
#if defined(__arm__)
#if defined(__ARM_ARCH_7A__)
#if defined(__ARM_NEON__)
#define ABI "armeabi-v7a/NEON"
#else
#define ABI "armeabi-v7a"
#endif
#else
#define ABI "armeabi"
#endif
#elif defined(__i386__)
#define ABI "x86"
#endif
//std::string hello("Hello from JNI !  Compiled with ABI " ABI ".");
std::string hello(stringFromJNI2(env, obj));
return env->NewStringUTF(hello.c_str());
}

下面是 TestNDK.java 文件的代码:

package com.test.ndk;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class TestNDK extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* Retrieve our TextView and set its content.
* the text is retrieved by calling a native
* function.
*/
setContentView(R.layout.activity_hello_jni);
TextView tv = (TextView)findViewById(R.id.hello_textview);
tv.setText( main() );
public native String main();
static {
//System.loadLibrary("main");
System.loadLibrary("TestNDK");
}
}

以下是 CMakeLists.txt 文件中的行:

cmake_minimum_required(VERSION 3.4.1)
add_library(testNDK SHARED
TestNDK.cpp
NDKTest.c)
# Include libraries needed for testNDK lib
target_link_libraries(testNDK
android
log)

以下是 build.gradle 文件中的代码:

apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion '25.0.2'
defaultConfig {
applicationId 'com.test.ndk'
minSdkVersion 23
targetSdkVersion 25
versionCode 1
versionName "1.0"
externalNativeBuild {
cmake {
arguments '-DANDROID_TOOLCHAIN=clang'
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
}
}
productFlavors {
arm7 {
// in the future, ndk.abiFilter might also work
ndk {
abiFilter 'armeabi-v7a'
}
}
arm8 {
ndk {
abiFilters 'arm64-v8a'
}
}
arm {
ndk {
abiFilter 'armeabi'
}
}
x86 {
ndk {
abiFilter 'x86'
}
}
x86_64 {
ndk {
abiFilter 'x86_64'
}
}
mips {
ndk {
abiFilters 'mips', 'mips64'
}
}
universal {
ndk {
abiFilters 'mips', 'mips64', 'x86', 'x86_64'
}
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:25.2.0'
compile 'com.android.support.constraint:constraint-layout:1.0.1'
}

由于TestNDK中的以下代码行.cpp,我目前收到以下错误"错误:(10,1)错误:C++需要所有声明的类型说明符"和"错误:(29,23)错误:调用'stringFromJNI2'是不明确的":

stringFromJNI2(JNIEnv *env, jobject obj);

这行代码位于外部"C"代码块中。 我正在尝试从TestNDK.cpp文件中调用NDKTest.c文件中的stringFromJni2()函数。 我将如何修复当前收到的错误,并调用 NDKTest.c 文件中的 stringFromJNI2() 函数以显示"来自 JNI2 的你好! 使用 ABI"字符串编译。 对此的任何帮助将不胜感激。 谢谢。

我正在尝试从 TestNDK.cpp 文件中调用 NDKTest.c 文件中的 stringFromJni2() 函数。

您应该在NDKTest.h中声明NDKTest.c中的函数原型。所以标题应该看起来像这样:

#ifndef NDKTEST_H_
#define NDKTEST_H_
#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
jstring Java_com_test_ndk_NDKTest_stringFromJNI2(JNIEnv *env, jobject thiz);
#ifdef __cplusplus
}
#endif
#endif

TestNDK.cpp

#include <jni.h>
#include "NDKTest.h"
#ifdef __cplusplus
extern "C" {
#endif
// remove this declaration
// stringFromJNI2(JNIEnv *env, jobject obj);
JNIEXPORT jstring JNICALL
Java_com_test_ndk_TestNDK_main(JNIEnv *env, jobject obj) {
#if defined(__arm__)
#if defined(__ARM_ARCH_7A__)
#if defined(__ARM_NEON__)
#define ABI "armeabi-v7a/NEON"
#else
#define ABI "armeabi-v7a"
#endif
#else
#define ABI "armeabi"
#endif
#elif defined(__i386__)
#define ABI "x86"
#endif
return Java_com_test_ndk_NDKTest_stringFromJNI2(env, obj);
}
#ifdef __cplusplus
}
#endif

TestNDK.java

// the library name has to be the same
// as you defined in CMakeLists.txt
static {
System.loadLibrary("testNDK");
}