Calling java from c++

M

Marcelo

Dear programmers,

I would like to know how to call java from c++. i am using JNI just for
doing the invers (calling c++ from java), but now I am quite lost.

I would like to use something like:

void jprintf(char *str){

//I want to do 2 prints
printf("In c++: %s", str):
...
//Calling :
... printJava(str);

}

with the java method as:

public void printJava(String str){
System.out.println("with java" +str);
}

But my problem as you see is that I don't have the ENV* or the obj*
pointers to play with...


thanks

Marcelo
 
T

Thomas Fritsch

Marcelo said:
Dear programmers,

I would like to know how to call java from c++. i am using JNI just for
doing the invers (calling c++ from java), but now I am quite lost. [...]
Calling Java from C/C++ is part of the JNI, too. It is specified in
<http://java.sun.com/j2se/1.4.2/docs/guide/jni/spec/jniTOC.html>
(Chapter 5. The Invocation API).
But, as Roedy already said, the spec is not targeted to beginners. You
will probably want to read a JNI text book about the "Invocation API".
 
M

Marcelo

thank you very much,

I have already made some little applications with jni (very littles).
How ever, I can't figure yet the whole power of the JNI (that's why I
need some help....).

thank you very very much

Marcelo
 
C

Chris Uppal

Marcelo said:
I have already made some little applications with jni (very littles).
How ever, I can't figure yet the whole power of the JNI (that's why I
need some help....).

I think you'll have to say more about the context of your problem. I can
imagine three scenarios where C++ code would call Java code, but they all have
different requirements.

The three are:

1) You have a C++ program, and you want to call Java code from it. In this
case you will need to learn how to start a new JVM instance and get a JNIEnv,
etc, from it.

2) You have a program which has several threads, some in Java and some in C++,
and you need to know how to talk to the existing JVM from the C++ threads.

3) You have a Java program which has called C++ code, and now the C++ code has
to call back into Java (so Java calls C++ calls Java).

-- chris
 
M

Marcelo

Actually the scenario that matchs the better to my problem is the second
one. I have already a virtual machine that have called a c++ routine.
However, this c++ routine is very independent.

So what i want to do is something like:

voir routine(int x){

....
env* = getCurrentJVM();

....
}

Do I need to create a new JVM instace or should I learn how to get the
current one.... I am not very sure...

thanks a lot

Marcelo
 
C

Chris Uppal

Marcelo said:
Actually the scenario that matchs the better to my problem is the second
one. I have already a virtual machine that have called a c++ routine.
However, this c++ routine is very independent.

So you /could/, in principle, pass the JNIEnv from where JNI is first invoked
all the way through (perhaps) many C++ calls to the place where it is to be
used; but you don't want to do that ? (Maybe that would require modifications
to code you don't have the right to change, or you simply don't want to screw
up your code's modularisation that badly.)

If that's the case then I think that you should use the JNI function GetEnv()
to find the JNIEnv appropriate for the thread you are running on. But that
leaves you with the problem of how to find the JavaVM that is needed to call
that... You will have to store that in some sort of global (or near global).
You could just record that in the first call to your JNI code (use
GetJavaVM() ), or there is a way of arranging for special code to be called
when your DLL is first loaded (a JNI_OnLoad() hook function in your DLL) so you
could record the JavaVM in that code. BTW, I wouldn't try keeping a JNIEnv in
a global variable instead, not even a thread-local variable, since JNIEnv
objects have a restricted lifetime (I think just for the duration of a single
call from Java to C++). You should keep the JavaVM in a global, and use
GetEnv() to find out which JNIEnv to use each time you enter your deeply nested
code. The JavaVM itself, though, is unique (you /cannot/ create another, even
if you try ;-) and can be used anywhere for the lifetime of the program (or at
least until the JVM is unloaded, but since your main program is in Java, that
won't happen until the program finishes).

I should admit that the previous paragraph is rather speculative since I have
never needed to use GetEnv() myself, and I may be missing something.

Sheng Liang's book is pretty helpful on such topics. If you don't have it
already, you can download it (free) from:
http://java.sun.com/docs/books/jni/index.html
and that page also has the usual links for buying a physical copy.

-- chris
 
J

John Perks and Sarah Mount

Chris Uppal said:
If that's the case then I think that you should use the JNI function GetEnv()
to find the JNIEnv appropriate for the thread you are running on. But that
leaves you with the problem of how to find the JavaVM that is needed to call
that...

JNI_GetCreatedJavaVMs fills a passed-in array with all the JVMs it can
find and can fit in the array, and sets another param to the number of
JVMs in total. If this result is greater than 1, panic. :)
The JavaVM itself, though, is unique (you /cannot/ create another, even
if you try ;-)

Only for the time being, apparently. The spec indicates that this might
be possible in a future version. One thing it rules out however is
multiple JVMs attached to the same (native) thread.
and can be used anywhere for the lifetime of the program (or at
least until the JVM is unloaded, but since your main program is in Java, that
won't happen until the program finishes).

Again, true for now, but this may change.

John.
 
C

Chris Uppal

John said:
JNI_GetCreatedJavaVMs fills a passed-in array with all the JVMs it can
find and can fit in the array, and sets another param to the number of
JVMs in total. If this result is greater than 1, panic. :)

Yes, that's another way. You still have to use a global to be able to call it,
though (in this case the handle to the JVM.DLL -- or the equivalent on Unix) so
it's not obvious what advantage it provides over just storing the JavaVM in a
global.

Only for the time being, apparently. The spec indicates that this might
be possible in a future version. One thing it rules out however is
multiple JVMs attached to the same (native) thread.

I wish !

Sun have stated (its on the bug parade somewhere) that they have no intention
ever of fullfilling the contract implied by the API. That's to say they have
no intention of ever:
-- allowing more than one JVM to exist in one
process at once
-- allowing a process that has created then destroyed
a JVM to create a second one.

I can't remember what reason they give for this, but I do remember that it
stuck me as specious at the time. Maybe it would make more sense if I re-read
it now, or maybe it would still stike me as bafflegab.

IBM and BEA apparently follow Sun in this since (the last time I tried) nether
of those implementations would allow it either.

-- chris
 
R

Roedy Green

Do I need to create a new JVM instace or should I learn how to get the
current one.... I am not very sure...

Starting up a new JVM is an expensive operation. You don't want to do
that if you don't have to. C++ can call Java and Java can call C++,
but usually it starts out with Java calling C++.

If C++ starts, then it needs to fire up a JVM the first time.

The bad news is JNI is more of a nightmare than you imagine. Best to
read up on it generally first to see what it is about rather than try
to learn it slice by slice to solve your immediate problems.

See http://mindprod.com/jgloss/jni.html
 

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,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top