Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can i implement two JNI methods with same name but different Params?

I have a java class with two native functions with same names but different parameters.

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

My header file looks like

#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_

and my cpp file

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

with only one function it works, but after add a second one with same name and different parameters I get an error:

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

I'm using android studio and experimental gradle plugin. What am I doing wrong?

like image 433
Morcl174 Avatar asked Mar 14 '16 15:03

Morcl174


People also ask

Can you have methods with same name?

Two methods may share the same name, provided the number of parameters are different, or if they both have the same parameters, then there is at least one position, i where the parameter types differ.

What is Jclass in JNI?

The jclass instance is your object on which a method will be invoked; you'll need to look up the getName method ID on the Class class, then invoke it on the jclass instance using CallObjectMethod to obtain a jstring result. So in short yes, you just call the getName function and look at the jstring result.

What is JNIEnv * env?

jobject NewGlobalRef(JNIEnv *env, jobject obj); Creates a new global reference to the object referred to by the obj argument. The obj argument may be a global or local reference. Global references must be explicitly disposed of by calling DeleteGlobalRef() .

What is JNA vs JNI?

Java Native Access (JNA) is a community-developed library that provides Java programs easy access to native shared libraries without using the Java Native Interface (JNI). JNA's design aims to provide native access in a natural way with a minimum of effort. Unlike JNI, no boilerplate or generated glue code is required.


2 Answers

First of all, if your native methods really take a jclass as their second argument then they should be declared static on the Java side. Otherwise they should take a jobject (the instance that they're invoked on) rather than a jclass.


Here's what Oracle's documentation says about naming of overloaded native methods:

A native method name is concatenated from the following components: ... for overloaded native methods, two underscores (“__”) followed by the mangled argument signature

So the name of your second function should be Java_com_example_Test_doSomething__IJ. You might also have to change the first function's name to Java_com_example_Test_doSomething__I.

like image 146
Michael Avatar answered Sep 21 '22 04:09

Michael


Use javah tool to generate header files, below is what this tool will generate for your class.

to use it first compile .java file, then run javah on .class file.

/* 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
like image 38
marcinj Avatar answered Sep 21 '22 04:09

marcinj