首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

Android JNI:Java 與 C++ 相互調用完整指南

     編輯:C++ 入門

一、Java 調用 C++ (JNI)

命名規則


// 返回類型 Java_包名_類名_方法名(JNIEnv*, jobject)
// 例:package com.ndk.testndk; class TestHello { native String jnia(); }
jstring Java_com_ndk_testndk_TestHello_jnia(JNIEnv* env, jobject obj);

關鍵點

  • C++ 文件需 extern "C" 防止名字修飾。
  • jobject 為調用對象實例(非靜態方法)或類對象(靜態方法)。
  • 返回基本類型直接用 jint、jboolean 等;對象類型用 jstring、jobject。
  • System.loadLibrary("TestNDK") 加載 libTestNDK.so。

二、C++ 調用 Java

核心步驟

  1. FindClass("com/ndk/testndk/TestHello2") 獲取 jclass。
  2. 實例化:AllocObject(cls) 或 GetMethodID(cls, "", "()V") + NewObject。
  3. 獲取方法 ID:
    • 靜態:GetStaticMethodID(cls, "method", "()Ljava/lang/String;")
    • 非靜態:GetMethodID(cls, "method", "(Ljava/lang/String;)Ljava/lang/String;")
  4. 調用:
    • 靜態:CallStaticObjectMethod(cls, mid)
    • 非靜態:CallObjectMethod(obj, mid, args...)

簽名規則速查

Java 類型JNI 簽名
intI
StringLjava/lang/String;
voidV
int[][I
ObjectLfull/package/Name;

方法簽名:(參數簽名)返回簽名,如 (ILjava/lang/String;)V。

完整示例代碼結構


// Java
public class TestHello {
    static { System.loadLibrary("TestNDK"); }
    native int jnia();
    native String jnistr();
}

// C++ (TestNDK.cpp)
#include 
#include 
extern "C" {
JNIEXPORT jint JNICALL Java_com_ndk_testndk_TestHello_jnia(JNIEnv* env, jobject obj) {
    return 12;
}
JNIEXPORT jstring JNICALL Java_com_ndk_testndk_TestHello_jnistr(JNIEnv* env, jobject obj) {
    jclass cls = env->FindClass("com/ndk/testndk/TestHello2");
    jobject obj1 = env->AllocObject(cls);
    jmethodID mid1 = env->GetStaticMethodID(cls, "getStaticString", "()Ljava/lang/String;");
    jmethodID mid2 = env->GetMethodID(cls, "getString", "(Ljava/lang/String;)Ljava/lang/String;");
    jstring jstr = (jstring)env->CallStaticObjectMethod(cls, mid1);
    jstring jstr2 = (jstring)env->CallObjectMethod(obj1, mid2, jstr);
    return jstr2;
}
}

常見坑點

  • 包名路徑:JNI 用 / 分隔,非 .。
  • 簽名錯誤導致 GetMethodID 返回 NULL。
  • 局部引用超出容量:長迴圈中需 DeleteLocalRef 或用 PushLocalFrame。
  • 線程安全:子線程需 AttachCurrentThread 獲取 JNIEnv*。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved