Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoke Java from C++

I am trying to invoke the Java Virtual machine from C++ following the example found here:

Basically I have a small Java program:

public class TestJNIInvoke
{
    public static void main(String[] args)
    {
    System.out.println(args[0]);
    }
}

Then I have a C++ program that I want to create a JVM and call the TestJNIInvoke class:

#include <jni.h>
#include <cstdlib>
#define PATH_SEPARATOR ';' /* define it to be ':' on Solaris */
#define USER_CLASSPATH "." /* where Prog.class is */

using namespace std;

int main() {
     JNIEnv *env;
     JavaVM *jvm;
     jint res;
     jclass cls;
     jmethodID mid;
     jstring jstr;
     jclass stringClass;
     jobjectArray args;

 #ifdef JNI_VERSION_1_2
     JavaVMInitArgs vm_args;
     JavaVMOption options[1];
     options[0].optionString =
         "-Djava.class.path=" USER_CLASSPATH;
     vm_args.version = 0x00010002;
     vm_args.options = options;
     vm_args.nOptions = 1;
     vm_args.ignoreUnrecognized = JNI_TRUE;
     /* Create the Java VM */
     res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
 #else
     JDK1_1InitArgs vm_args;
     char classpath[1024];
     vm_args.version = 0x00010001;
     JNI_GetDefaultJavaVMInitArgs(&vm_args);
     /* Append USER_CLASSPATH to the default system class path */
     sprintf(classpath, "%s%c%s",
             vm_args.classpath, PATH_SEPARATOR, USER_CLASSPATH);
     vm_args.classpath = classpath;
     /* Create the Java VM */
     res = JNI_CreateJavaVM(&jvm, &env, &vm_args);
 #endif /* JNI_VERSION_1_2 */

     if (res < 0) {
         fprintf(stderr, "Can't create Java VM\n");
         exit(1);
     }
     cls = (*env)->FindClass(env, "TestJNIInvoke");
     if (cls == NULL) {
         goto destroy;
     }

     mid = (*env)->GetStaticMethodID(env, cls, "main",
                                     "([Ljava/lang/String;)V");
     if (mid == NULL) {
         goto destroy;
     }
     jstr = (*env)->NewStringUTF(env, " from CPP!");
     if (jstr == NULL) {
         goto destroy;
     }
     stringClass = (*env)->FindClass(env, "java/lang/String");
     args = (*env)->NewObjectArray(env, 1, stringClass, jstr);
     if (args == NULL) {
         goto destroy;
     }
     (*env)->CallStaticVoidMethod(env, cls, mid, args);

 destroy:
     if ((*env)->ExceptionOccurred(env)) {
         (*env)->ExceptionDescribe(env);
     }
     (*jvm)->DestroyJavaVM(jvm);
 }

But When I try to compile the C++ program I get this error:

c:\java\JNI> g++ -I"c:\Program Files\Java\jdk1.7.0\include"-I"c:\ProgramFiles\Java\jdk1.7.0\include\win32" -c TestJNIInvoke.cpp


TestJNIInvoke.cpp: In function 'int main()':
TestJNIInvoke.cpp:20:31: warning: deprecated conversion from string constant to
'char*'
TestJNIInvoke.cpp:44:18: error: base operand of '->' has non-pointer type 'JNIEn
v'
TestJNIInvoke.cpp:49:18: error: base operand of '->' has non-pointer type 'JNIEn
v'
TestJNIInvoke.cpp:54:19: error: base operand of '->' has non-pointer type 'JNIEn
v'
TestJNIInvoke.cpp:58:26: error: base operand of '->' has non-pointer type 'JNIEn
v'
TestJNIInvoke.cpp:59:19: error: base operand of '->' has non-pointer type 'JNIEn
v'
TestJNIInvoke.cpp:63:12: error: base operand of '->' has non-pointer type 'JNIEn
v'
TestJNIInvoke.cpp:66:16: error: base operand of '->' has non-pointer type 'JNIEn
v'
TestJNIInvoke.cpp:67:16: error: base operand of '->' has non-pointer type 'JNIEn
v'
TestJNIInvoke.cpp:69:12: error: base operand of '->' has non-pointer type 'JavaVM'

Any ideas?

Thanks

like image 780
Hunter McMillen Avatar asked Sep 24 '11 21:09

Hunter McMillen


People also ask

How can I call a Java program from C program?

To call a specific Java function from C, you need to do the following: Obtain the class reference using the FindClass(,,) method. Obtain the method IDs of the functions of the class that you want to call using the GetStaticMethodID and GetMethodID function calls.

How can I call C function in Java using native keyword?

Use javah -jni to generate a C header file ( HelloWorld. h ) containing the function prototype for the native method implementation. The javah tool is provided with JDK or Java 2 SDK releases. Write the C implementation ( HelloWorld.

Can we run Java in Dev C++?

Code in Java, Execute as C++. Depending on the problem, one might work better than the other. However, at some point, we need to integrate these languages, e.g. calling a method written in Java to your C++ code. The need to integrate Java and C++ is not something new. In fact, we can find a tutorial dated back to 1996.


2 Answers

Even though you include the same header file, the Java Native Interface uses two different interfaces for C and C++.

In C++, it's:

jclass cls = env->FindClass("java/lang/String");

instead of (for C):

jclass cls = (*env)->FindClass(env, "java/lang/String");

So the C function call that requires env in two places becomes a convenient member function call in C++.

This is mentioned in the Native Method Arguments section of the Java Native Interface 6.0 Specification.

like image 154
Codo Avatar answered Oct 20 '22 18:10

Codo


My guess would be that you're attempting to compile against the win32 headers given the command line you're using. Have you tried -I"c:\ProgramFiles\Java\jdk1.7.0\include\solaris instead (assuming that's your platform based on the comment higher up in the source).

like image 33
russw_uk Avatar answered Oct 20 '22 16:10

russw_uk