我如何实现两个名称相同但参数不同的 JNI 方法?
How can i implement two JNI methods with same name but different Params?
我有一个 java class,其中包含两个名称相同但参数不同的本机函数。
package com.example;
public class Test {
static {
System.loadLibrary("TestLib");
}
public static native void doSomething(int a);
public static native void doSomething(int a, long b);
}
我的头文件看起来像
#include <jni.h>
#ifndef _TEST_LIB_H_
#define _TEST_LIB_H_
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_com_example_Test_doSomething
(JNIEnv *env, jclass clazz, jint a);
JNIEXPORT void JNICALL Java_com_example_Test_doSomething
(JNIEnv *env, jclass clazz, jint a, jlong b);
#ifdef __cplusplus
}
#endif
#endif //_TEST_LIB_H_
和我的 cpp 文件
#include "TestLib.h"
JNIEXPORT void JNICALL Java_com_example_Test_doSomething
(JNIEnv *env, jclass clazz, jint a){
Java_com_example_Test_doSomething(env, clazz, a, -1);
}
JNIEXPORT void JNICALL Java_com_example_Test_doSomething
(JNIEnv *env, jclass clazz, jint a, jlong b) {
// implementation
}
只有一个功能有效,但在添加第二个具有相同名称和不同参数的功能后,我收到错误消息:
error: conflicting declaration of C function 'void Java_com_example_Test_doSomething(JNIEnv*, jclass, jint, jlong)'
note: previous declaration 'void Java_com_example_Test_doSomething(JNIEnv*, jclass, jint)'
我正在使用 android 工作室和实验性 gradle 插件。
我做错了什么?
首先,如果您的本机方法确实将 jclass
作为第二个参数,那么它们应该在 Java 端声明为 static
。否则他们应该采用 jobject
(调用它们的实例)而不是 jclass
.
以下是 Oracle's documentation 关于重载本机方法命名的内容:
A native method name is concatenated from the following components:
...
for overloaded native methods, two underscores (“__”) followed by the mangled argument signature
所以你的第二个函数的名称应该是Java_com_example_Test_doSomething__IJ
。您可能还必须将第一个函数的名称更改为 Java_com_example_Test_doSomething__I
.
使用javah工具生成头文件,下面是这个工具会为你的class.
生成的内容
要使用它,首先编译 .java 文件,然后 运行 javah 在 .class 文件上。
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_Test */
#ifndef _Included_com_example_Test
#define _Included_com_example_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_Test
* Method: doSomething
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_example_Test_doSomething__I
(JNIEnv *, jobject, jint);
/*
* Class: com_example_Test
* Method: doSomething
* Signature: (IJ)V
*/
JNIEXPORT void JNICALL Java_com_example_Test_doSomething__IJ
(JNIEnv *, jobject, jint, jlong);
#ifdef __cplusplus
}
#endif
#endif
我有一个 java class,其中包含两个名称相同但参数不同的本机函数。
package com.example;
public class Test {
static {
System.loadLibrary("TestLib");
}
public static native void doSomething(int a);
public static native void doSomething(int a, long b);
}
我的头文件看起来像
#include <jni.h>
#ifndef _TEST_LIB_H_
#define _TEST_LIB_H_
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_com_example_Test_doSomething
(JNIEnv *env, jclass clazz, jint a);
JNIEXPORT void JNICALL Java_com_example_Test_doSomething
(JNIEnv *env, jclass clazz, jint a, jlong b);
#ifdef __cplusplus
}
#endif
#endif //_TEST_LIB_H_
和我的 cpp 文件
#include "TestLib.h"
JNIEXPORT void JNICALL Java_com_example_Test_doSomething
(JNIEnv *env, jclass clazz, jint a){
Java_com_example_Test_doSomething(env, clazz, a, -1);
}
JNIEXPORT void JNICALL Java_com_example_Test_doSomething
(JNIEnv *env, jclass clazz, jint a, jlong b) {
// implementation
}
只有一个功能有效,但在添加第二个具有相同名称和不同参数的功能后,我收到错误消息:
error: conflicting declaration of C function 'void Java_com_example_Test_doSomething(JNIEnv*, jclass, jint, jlong)'
note: previous declaration 'void Java_com_example_Test_doSomething(JNIEnv*, jclass, jint)'
我正在使用 android 工作室和实验性 gradle 插件。 我做错了什么?
首先,如果您的本机方法确实将 jclass
作为第二个参数,那么它们应该在 Java 端声明为 static
。否则他们应该采用 jobject
(调用它们的实例)而不是 jclass
.
以下是 Oracle's documentation 关于重载本机方法命名的内容:
A native method name is concatenated from the following components: ... for overloaded native methods, two underscores (“__”) followed by the mangled argument signature
所以你的第二个函数的名称应该是Java_com_example_Test_doSomething__IJ
。您可能还必须将第一个函数的名称更改为 Java_com_example_Test_doSomething__I
.
使用javah工具生成头文件,下面是这个工具会为你的class.
生成的内容要使用它,首先编译 .java 文件,然后 运行 javah 在 .class 文件上。
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_Test */
#ifndef _Included_com_example_Test
#define _Included_com_example_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_Test
* Method: doSomething
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_example_Test_doSomething__I
(JNIEnv *, jobject, jint);
/*
* Class: com_example_Test
* Method: doSomething
* Signature: (IJ)V
*/
JNIEXPORT void JNICALL Java_com_example_Test_doSomething__IJ
(JNIEnv *, jobject, jint, jlong);
#ifdef __cplusplus
}
#endif
#endif