How to Call Java Functions from C++

How to call Java functions from C++?

As an example, check Creating a JVM from C. It shows a sample procedure to create a JVM and invoke a method. If the JVM already exists; e.g. your C program is invoked by the Java program (callback situation), you can cache the JNIEnv* pointer.

As an advice, be careful caching pointers to the JVM from C/C++, there are some semantics involved as to what you can cache and it could be invoked later on. For that, as Brian Agnew pointed out, check the JNI reference.

Calling Java functions from C language

I solved this by making my class into my own package.
When we did not define any package it is taking as default package.
So I created my own package something like this

package com.aqu.vvn

I know its a work around but doing this worked for me.
I will let u know the exact way when I figured out.

Calling Java methods from C without starting the JVM from C

As JJF stated, this is definitely possible! I'll show an example below, assuming you already know how to call Java methods from C, but without having to create a JVM!

First, we have a Java class test.Test.java that calls the native method methodA:

package test;

public class Test {
static {
System.loadLibrary("test");
}

private native void methodA();

public static void methodB() {
System.out.println("Java: Method B has executed!");
}

public static void main(String[] args) {
new Test().methodA();
}
}

Next, we have the header file created by javah or javac -h:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class test_Test */

#ifndef _Included_test_Test
#define _Included_test_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: test_Test
* Method: methodA
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_test_Test_methodA
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

Below is the C file which holds the native method methodA:

#include <jni.h>
#include <stdio.h>
#include "test_Test.h"


void callMethodB(JNIEnv *env);

JNIEXPORT void JNICALL Java_test_Test_methodA(JNIEnv *env, jobject thisObj) {
printf("C: Method A executed!\n"); fflush(stdout);
callMethodB(env);
return;
}

void callMethodB(JNIEnv *env) {
jclass testClass = (*env) -> FindClass(env, "test/Test");
jmethodID methodB = (*env) -> GetStaticMethodID(env, testClass, "methodB", "()V");
(*env) -> CallStaticVoidMethod(env, testClass, methodB, NULL);
return;
}

The output of this program is:

C: Method A executed!

Java: Method B has executed!

Remember to create a test.dll file with your preferred GNU compiler.

Call Java function from C++ method

As an example, check Creating a JVM from C. It shows a sample procedure to create a JVM and invoke a method. If the JVM already exists; e.g. your C program is invoked by the Java program (callback situation), you can cache the JNIEnv* pointer.

As an advice, be careful caching pointers to the JVM from C/C++, there are some semantics involved as to what you can cache and it could be invoked later on.

Source: How to call Java functions from C++?

How to call Java function from c

You can't reuse JNIEnv because it is specific to the calling thread. To call (non-static) Java method from the native code, you need something like this:

static JavaVM *gJavaVM;
static jobject gCallbackObject = NULL;

JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
gJavaVM = vm;
return JNI_VERSION_1_6;
}

JNIEXPORT void JNICALL JNI_FUNCTION(AndroidActivity_nativeInit)(JNIEnv* env, jobject obj, int width, int height) {
// ...
gCallbackObject = (*env)->NewGlobalRef(env, obj);
}

JNIEXPORT void JNICALL JNI_FUNCTION(AndroidActivity_nativeRelease)(JNIEnv* env, jobject obj) {
(*env)->DeleteGlobalRef(env, gCallbackObject);
gCallbackObject = NULL;
}

//this method is called from native code
void nativeSayHello(char* msg) {
int status;
JNIEnv *env;
int isAttached = 0;

if (!gCallbackObject) return;

if ((status = (*gJavaVM)->GetEnv(gJavaVM, (void**)&env, JNI_VERSION_1_6)) < 0) {
if ((status = (*gJavaVM)->AttachCurrentThread(gJavaVM, &env, NULL)) < 0) {
return;
}
isAttached = 1;
}

jclass cls = (*env)->GetObjectClass(env, gCallbackObject);
if (!cls) {
if (isAttached) (*gJavaVM)->DetachCurrentThread(gJavaVM);
return;
}

jmethodID method = (*env)->GetMethodID(env, cls, "SayHello", "(Ljava/lang/String;)V");
if (!method) {
if (isAttached) (*gJavaVM)->DetachCurrentThread(gJavaVM);
return;
}

jstring string = (*mEnv)->NewStringUTF(mEnv, msg);
(*env)->CallVoidMethod(env, gCallbackObject, method, string);

if (isAttached) (*gJavaVM)->DetachCurrentThread(gJavaVM);
}

This code snippet is not tested. To prevent memory leak, don't forget to call nativeRelease() method in your Java code when the reference to the object will not needed any more.

See The Java Native Interface documentation for more details.



Related Topics



Leave a reply



Submit