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
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.
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.
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.
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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With