2017-04-10 221 views
1

我試圖從NDKTest.c文件中調用stringFromJNI2(env,obj)函數。從C++函數調用C函數在Android中JNI/NDK代碼

下面是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' 
} 

目前,我發現了以下錯誤「錯誤:(10,1)錯誤:C++需要所有聲明的類型說明符」&「錯誤:(29,23)錯誤:由於TestNDK.cpp中的以下代碼行,調用'stringFromJNI2'是不明確的:

stringFromJNI2(JNIEnv *env, jobject obj); 

這行代碼位於extern「C」代碼塊中。我試圖從TestNDK.cpp文件的NDKTest.c文件中調用stringFromJni2()函數。我將如何修復當前出現的錯誤,並在NDKTest.c文件中調用stringFromJNI2()函數以顯示「來自JNI2的Hello!Compiled with ABI」字符串。任何幫助,將不勝感激。謝謝。

回答

3

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

你應該申報從NDKTest.c函數原型NDKTest.h。因此,頭部應該是這樣的:

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