简体   繁体   中英

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

I'm trying to call the stringFromJNI2(env, obj) function from the NDKTest.c file.

Here is the code for the NDKTest.c File:

#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 ".");

}

Here is the code for the NDKTest.h File:

#ifndef NDKTEST_H_
#define NDKTEST_H_

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

const std::allocator<char> & stringFromJNI2(JNIEnv *env, jobject thiz);

#endif

Here is the code for the TestNDK.cpp File:

#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());
}

Here is the code for the TestNDK.java File:

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");
    }
}

Here are the lines in the CMakeLists.txt File:

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)

Here is the code from the build.gradle file:

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'
}

I'm currently getting the following errors "Error:(10, 1) error: C++ requires a type specifier for all declarations" & "Error:(29, 23) error: call to 'stringFromJNI2' is ambiguous" due to the following line of code in TestNDK.cpp:

stringFromJNI2(JNIEnv *env, jobject obj);

This line of the code in located in the extern "C" block of code. I'm trying to call the stringFromJni2() function in the NDKTest.c file from the TestNDK.cpp file. How would I fix the current errors I'm getting and call the stringFromJNI2() function in the NDKTest.c file to display the "Hello from JNI2 ! Compiled with ABI" string. Any help on this would be greatly appreciated. Thanks.

I'm trying to call the stringFromJni2() function in the NDKTest.c file from the TestNDK.cpp file.

You should declare the function prototype from NDKTest.c in NDKTest.h . So the header should look like this:

#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");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM