Under Linux, Call java from C++

T

tony_lincoln

Dear Friends,

Under Linux, I tried to call java from C++ using JNI. The following is
the C++ code which calls one java class named Menu_3D.
When I compiled it using g++, there were many mistakes like:

........
invoke.cpp:26: error: 'struct JavaVMInitArgs' has no member named
'version'
invoke.cpp:26: error: `JNI_VERSION_1_4' undeclared (first use this
function)
invoke.cpp:27: error: 'struct JavaVMInitArgs' has no member named
'nOptions'
invoke.cpp:31: error: `jint' undeclared (first use this function)
invoke.cpp:31: error: syntax error before `=' token
invoke.cpp:32: error: `res' undeclared (first use this function)
invoke.cpp:41: error: `FindClass' undeclared (first use this function)
invoke.cpp:50: error: `GetStaticMethodID' undeclared (first use this
function)
invoke.cpp:56: error: `NewObjectArray' undeclared (first use this
function)
invoke.cpp:60: error: `CallStaticVoidMethod' undeclared (first use this
function)
invoke.cpp:73: error: `DestroyJavaVM' undeclared (first use this
function)
........

The above errors are only one part of the whole errors. I know that I
am wrong in this line:
"#pragma comment
(lib,"E:\\Programme\\Java\\jdk1.5.0_02\\lib\\jvm.lib")"

But how can I find the jvm.lib? I tried and I can not. Does invoke.cpp
need jvm.lib under Linux?

Or are there other reasons to cause the errors?
Thanks a lot
tony


__________________________________________________________________________
/*for C++,debugged with Visual C++ 6.0*/

#ifndef __cplusplus
#define __cplusplus
#endif

#include "jni.h"
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#pragma comment (lib,"E:\\Programme\\Java\\jdk1.5.0_02\\lib\\jvm.lib")

void main() {

JavaVM *jvm;
JNIEnv *env;

JavaVMInitArgs vm_args;
JavaVMOption options[3];

options[0].optionString = "-Djava.compiler=NONE";
options[1].optionString = "-Djava.classpath=.";
options[2].optionString = "-verbose:jni";

vm_args.version = JNI_VERSION_1_4;
vm_args.nOptions = 3;
vm_args.options = options;
vm_args.ignoreUnrecognized = JNI_TRUE;

jint res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
if (res < 0) {
fprintf(stderr, "Can't create Java VM\n");
exit(1);
};


// jclass cls = env->FindClass("DemoMain");
// This sentence can work. Just put it into the same directory as
invoke.cpp.

jclass cls = env->FindClass("Menu_3D");
if (cls == 0) printf("Sorry, I can't find the class");

fprintf(stdout, "This is invokeSimplified4.\n");

jmethodID get_main_id;

if(cls != NULL)
{
get_main_id =
env->GetStaticMethodID(cls,"main","([Ljava/lang/String;)V");
fprintf(stdout, "This is invokeSimplified5.\n");

if(get_main_id != NULL )
{
jclass string = env->FindClass("java/lang/String");
jobjectArray args = env->NewObjectArray(0,string, NULL);

fprintf(stdout, "This is invokeSimplified6.\n");

env->CallStaticVoidMethod(cls, get_main_id, args);
/*
if (env->ExceptionOccurred())
{
env->ExceptionDescribe();
env->ExceptionClear();
}
*/ fprintf(stdout, "This is invokeSimplified7.\n");
}// end IF.

}// end IF.


jvm->DestroyJavaVM();
fprintf(stdout, "Java VM destory\n");
}//end main.
______________________________________________________codes end.
 
G

Gordon Beaton

Under Linux, I tried to call java from C++ using JNI. The following
is the C++ code which calls one java class named Menu_3D. When I
compiled it using g++, there were many mistakes

I don't get the errors you report, but there are some things that need
to be fixed:

- main() must return int, not void.

- #include <windows.h> isn't necessary at all, remove it
(anyway I suspect you don't have such a file on linux).

- normally you should include the system header files first, followed
by jni.h and finally your own header files.

- the pragma is unknown to g++

After making the above changes, the code compiles fine using the
following commands:

(compile: invoke.cpp -> invoke.o)
gcc -Wall -D_REENTRANT -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -c invoke.cpp

(link: invoke.o -> invoke)
gcc -L $JAVA_HOME/jre/lib/i386/client invoke.o -lstdc++ -ljvm -lpthread -o invoke

(note that each of these two commands is exactly one line, even though
my newsreader or yours may have broken them)

To run the program you need to have the following directories in your
LD_LIBRARY_PATH:

$JAVA_HOME/jre/lib/i386/client
$JAVA_HOME/jre/lib/i386

/gordon
 
R

Roedy Green

LD_LIBRARY_PATH

what is LD_LIBRARY_PATH? a system property, a SET environment
parameter? just a name for the path? I was looking for signs of it
today earlier on my Windows machine. Nothing. I vaguely recall seeing
it earlier..
 
G

Gordon Beaton

what is LD_LIBRARY_PATH? a system property, a SET environment
parameter? just a name for the path? I was looking for signs of it
today earlier on my Windows machine. Nothing. I vaguely recall seeing
it earlier..

One of several enviroment variables that can be used to control the
dynamic linker/loader. They are described on the relevant man pages
(e.g. man ld.so on linux).

/gordon
 
T

tony_lincoln

Hi Friends and especially Gordon,

Thanks a lot for the words. I did the following:
1.changed the path setting :
export
LD_LIBRARY_PATH=$JAVA_HOME/jre/lib/i386/client:$JAVA_HOME/jre/lib/i386.
2. changed "void main()" into "int main()"

THen the erros are like this:
____________________________________________________________________
rakta:~/jniLinux$ gcc -Wall -D_REENTRANT -I $JAVA_HOME/include -I
$JAVA_HOME/include/linux -c invokeLinux.cpp
invokeLinux.cpp: In function `int main()':
invokeLinux.cpp:24: error: `JNI_VERSION_1_4' undeclared (first use this
function)
invokeLinux.cpp:24: error: (Each undeclared identifier is reported only
once
for each function it appears in.)
__________________________________________________________________________________

line 24 in invokeLinux.cpp is:
vm_args.version = JNI_VERSION_1_4;

Is there anything wrong with the version of JVM?
Thanks in advance.
tony
 
J

Jeff Schwab

Roedy said:
what is LD_LIBRARY_PATH? a system property, a SET environment
parameter? just a name for the path? I was looking for signs of it
today earlier on my Windows machine. Nothing. I vaguely recall seeing
it earlier..

LD_LIBRARY_PATH is an environment variable used to tell some linkers
where to look for libraries. I have found it useful with the GNU tools
on various flavors of Unix.
 
T

tony_lincoln

When I remove this line,
vm_args.version = JNI_VERSION_1_4;

I can get invoke.o and invoke. But when I typed invoke, there is one
error:
error while loading shared libraries: libjvm.so: cannot open shared
object file: No such file or directory

I guess that is the problem about LD_LIBRARY_PATH. But I set it already
in bashrc file...
Why?
 
G

Gordon Beaton

When I remove this line,
vm_args.version = JNI_VERSION_1_4;

It sounds like you are using an earlier version of java - try using
JNI_VERSION_1_2, or check the value of JAVA_HOME.

What does "java -version" say?
I can get invoke.o and invoke. But when I typed invoke, there is one
error:
error while loading shared libraries: libjvm.so: cannot open shared
object file: No such file or directory

I guess that is the problem about LD_LIBRARY_PATH. But I set it already
in bashrc file...

LD_LIBRARY_PATH is what I'd check too. Where does JAVA_HOME point? Can
you find libjvm.so yourself somewhere in or below JAVA_HOME?

/gordon
 
T

tony_lincoln

I set the path like this:

export
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/jvm/java-1.4.2-sun-1.4.2.05/jre/lib/i386/server/

This time I can compile it and got invoke.o and invoke. But when I type
invoke
then the new information comes:
Can't create Java VM

I really wonder why?
 
T

tony_lincoln

I found two libjvm.so.
/usr/lib/jvm/java-1.4.2-sun-1.4.2.05/jre/lib/i386/client/libjvm.so
/usr/lib/jvm/java-1.4.2-sun-1.4.2.05/jre/lib/i386/server/libjvm.so
I know that they are different. But what is the difference?
 
G

Gordon Beaton

I set the path like this:

export
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/jvm/java-1.4.2-sun-1.4.2.05/jre/lib/i386/server/

This time I can compile it and got invoke.o and invoke. But when I type
invoke
then the new information comes:
Can't create Java VM

I really wonder why?

You need to add *two* directories to LD_LIBRARY_PATH:

/usr/lib/jvm/java-1.4.2-sun-1.4.2_05/jre/lib/i386/server
/usr/lib/jvm/java-1.4.2-sun-1.4.2_05/jre/lib/i386

/gordon
 
T

tony_lincoln

You are right. My java version is 1.4.2_05.
So I changed the codes into
vm_args.version = JNI_VERSION_1_4_2_05;

But the error kept the same:

rakta:~/GAQ$ gcc -Wall -D_REENTRANT -I
/home/gao/java/j2sdk1.4.2_08/include -I
/home/gao/java/j2sdk1.4.2_08/include/linux-c invokeLinux.cpp
invokeLinux.cpp: In function `int main()':
invokeLinux.cpp:24: error: `JNI_VERSION_1_4_2_05' undeclared (first use
this
function)
invokeLinux.cpp:24: error: (Each undeclared identifier is reported only
once
for each function it appears in.)

:-(
 
T

tony_lincoln

Yes. I changed the path into:

rakta:~/GAQ$ export
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/jvm/java-1.4.2-sun-1.4.2_05/jre/lib/i386/server:/usr/lib/jvm/java-1.4.2-sun-1.4.2_05/jre/lib/i386

Then compile it, and the error kept the same:

invokeLinux.cpp: In function `int main()':
invokeLinux.cpp:24: error: `JNI_VERSION_1_4_2_05' undeclared (first use
this
function)
invokeLinux.cpp:24: error: (Each undeclared identifier is reported only
once
for each function it appears in.)

If I remove the line "vm_args.version = JNI_VERSION_1_4_2_05",
I can compile it, but the final result kept the same:
"Can't create Java VM"

Sorry for my questions.
 
G

Gordon Beaton

You are right. My java version is 1.4.2_05.
So I changed the codes into
vm_args.version = JNI_VERSION_1_4_2_05;

But the error kept the same:

rakta:~/GAQ$ gcc -Wall -D_REENTRANT -I
/home/gao/java/j2sdk1.4.2_08/include -I
/home/gao/java/j2sdk1.4.2_08/include/linux-c invokeLinux.cpp
invokeLinux.cpp: In function `int main()':
invokeLinux.cpp:24: error: `JNI_VERSION_1_4_2_05' undeclared (first use
this
function)
invokeLinux.cpp:24: error: (Each undeclared identifier is reported only
once
for each function it appears in.)

The only valid values are (AFAIK) JNI_VERSION_1_4, JNI_VERSION_1_2 and
JNI_VERSION_1_1, they are listed in jni.h.

The paths you mention in the example above don't agree with what
you've posted elsewhere, where you mentioned
/usr/lib/jvm/java-1.4.2-sun-1.4.2_05.

It seems you have several java versions installed. You need to make
sure you compile and link against the correct (and same) one.

/gordon
 
G

Gordon Beaton

Yes. I changed the path into:

rakta:~/GAQ$ export
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/jvm/java-1.4.2-sun-1.4.2_05/jre/lib/i386/server:/usr/lib/jvm/java-1.4.2-sun-1.4.2_05/jre/lib/i386

Then compile it, and the error kept the same:

LD_LIBRARY_PATH has nothing to do with compiling the code. It's only
there to help find the libraries that are needed when you *run* the
program.
invokeLinux.cpp: In function `int main()':
invokeLinux.cpp:24: error: `JNI_VERSION_1_4_2_05' undeclared (first use
this
function)
invokeLinux.cpp:24: error: (Each undeclared identifier is reported only
once
for each function it appears in.)

If I remove the line "vm_args.version = JNI_VERSION_1_4_2_05",
I can compile it, but the final result kept the same:
"Can't create Java VM"

I've responded to this in another post. This JNI_VERSION isn't valid.

/gordon
 
T

tony_lincoln

Thanks. I think that you are correct. I will try to compile and link
against the correct (and same) version tomorrow.
Thanks a lot and Have a nice weekend.
tony
 
R

Roedy Green

I know that they are different. But what is the difference?

there are two versions of java.exe and its attendant dlls. You
control which one you get with the -server command line option.

The -server version is slower to start, but presumes it will keep
running the same code for a long time, so spends more time optimising
it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top