Java <-> MFC?

T

Tim Ward

I've got this MFC application which needs some functionality (basically a
protocol stack and some application layer stuff) that I've only got in Java.
From the MFC application I need to

(a) start up the Java application, with no GUI
(b) tell it what to do
(c) check its progress (the operation will take several minutes)
(d) cancel it if the user gets bored
(e) retrieve results from the Java application and display them in the MFC
GUI.

Now, this is to be a quick and dirty hack to fill a temporary need - if I
were doing this "properly" I'd probably re-implement the protocol stack in
C++, but I want something quicker than that.

I don't need the Java application to throw events back at the C++ one,
polling for progress and results would be good enough (because it's a
temporary fudge).

Clearly I can communicate between the C++ and Java applications by several
means:

(1) the C++ application can put stuff into Java's stdin and read results
from Java's stdout
(2) I can set up a socket connection between the two applications and design
and write a quick dirty private protocol
(3) if I were feeling really uninventive they could communicate with disk
files (yuk, even for a quick hack).

Are there other suggests for communication that meet the requirement of
being quick and easy to implement? For example, is there some COM gateway I
could wrap round the Java application to make it look like a COM server?
(Corba is over the top, I'm not going there.)
 
D

Daniel Dyer

Clearly I can communicate between the C++ and Java applications by
several
means:

(1) the C++ application can put stuff into Java's stdin and read results
from Java's stdout
(2) I can set up a socket connection between the two applications and
design
and write a quick dirty private protocol
(3) if I were feeling really uninventive they could communicate with disk
files (yuk, even for a quick hack).

Are there other suggests for communication that meet the requirement of
being quick and easy to implement? For example, is there some COM
gateway I
could wrap round the Java application to make it look like a COM server?
(Corba is over the top, I'm not going there.)

You could use the Java Native Interface to fire up the JVM from the
C++ app then use JNI to call the methods of your Java app.

Dan.
 
T

Tim Ward

Daniel Dyer said:
You could use the Java Native Interface to fire up the JVM from the
C++ app then use JNI to call the methods of your Java app.

So you can, thanks! - I hadn't realised that, all I'd remembered reading on
JNI was that it allowed Java applications to call bits of code written in
other languages, not the other way round.
 
T

Thomas Weidenfeller

Tim said:
Clearly I can communicate between the C++ and Java applications by several
means:

(1) the C++ application can put stuff into Java's stdin and read results
from Java's stdout

That's what I would probably do for a quick hack. Note that I am
primarily a Unix hacker, and that's what people like to do on Unix.
(2) I can set up a socket connection between the two applications and design
and write a quick dirty private protocol

You would also have to do some protocol if you use stdin/stdout. But
here you would also have to do the socket handling. I wouldn't do it.
(3) if I were feeling really uninventive they could communicate with disk
files (yuk, even for a quick hack).

Are there other suggests for communication that meet the requirement of
being quick and easy to implement? For example, is there some COM gateway I
could wrap round the Java application to make it look like a COM server?

You should already have an ActiveX wrapper installed on your disk,
because such a beast comes with every Sun JDK for Windows:

http://java.sun.com/j2se/1.5.0/docs/guide/beans/axbridge/developerguide/index.html

/Thomas
 
G

Giovanni Azua

Hello Tim,

Looks like you really did your homework :) I would also
firstly think about all those choices you have considered
but if you really want something to "put on top of your CV"
have a look at the project JCom:

http://www.nexb.org/open-source-it-asset-management/Wiki.jsp?page=Jcom
http://sourceforge.net/projects/jcom

implements a bridge Java - COM ... is the only free one I have
found but you will find plenty of them using Google. I bet "Java -COM
bridge" will definitely put recruiters and project managers in extasy :)

HTH,
Best Regards,
Giovanni
 
T

Tim Ward

Daniel Dyer said:
You could use the Java Native Interface to fire up the JVM from the
C++ app then use JNI to call the methods of your Java app.

Hmmm ... but how to find out what needs fixing when JNI_CreateJavaVM
returns -1? - not much of a clue there.
 
D

Daniel Dyer

Hmmm ... but how to find out what needs fixing when JNI_CreateJavaVM
returns -1? - not much of a clue there.

You're on your own ;) I've only used JNI the other way around (Java
calling C++).

Dan.
 
T

Tim Ward

Daniel Dyer said:
You're on your own ;) I've only used JNI the other way around (Java
calling C++).

OK, so a bit of reading around says you can't just copy jvm.dll into your
application's directory, it insists on being run from its installed
location. So, make jvm.dll's installed location the current directory when I
run my test app. At which point JNI_CreateJavaVM works.

BUT

(1) That's OK for me hacking around but obviously not useful for deployment,
when the user might have who-knows-which version of the JRE installed
who-knows-where. The installation process for my MFC app couldn't add the
location of jvm.dll to the path because it hasn't a clue where it is (even
if I wanted to mess with the user's path for such a small new feature of my
app, which I don't). How do people solve this one?

AND

(2) I can now run a method in my jar. Which creates a Swing GUI (I'll switch
that off in due course, but during development it's obviously helpful to see
whether the spawned Java app exists and is doing anything useful). But how
to close the spawned app?

(a) calling DestroyJavaVM() isn't helpful - it doesn't return - hints in the
documentation suggest that its probably waiting for all the threads in the
Java application to terminate, which they aren't going to; that's fair
enough I guess

(b) closing the Swing GUI in the normal way (click on the window close box)
ends up in a (Java) call of System.exit(0); which takes down the calling C++
application! No! No! Surely not! How could I possibly want that?? Closing
the Java application should take down the Java application, and I'm not too
bothered about whether it takes down the Java VM as well, but what on earth
was going through the head of the person who decided it would be a good idea
to take down the calling native application as well????? (Which it doesn't
do cleanly anyway, it crashes in _exit() in the C RTL when unwinding
something to do with thread local storage.)

Clearly there's a bit of a learning curve with this technology ... any help
would be most welcome :)
 
G

Giovanni Azua

Tim Ward said:
(b) closing the Swing GUI in the normal way (click on the window close
box)
ends up in a (Java) call of System.exit(0); which takes down the calling
C++
application! No! No! Surely not! How could I possibly want that?? Closing
the Java application should take down the Java application, and I'm not
too
bothered about whether it takes down the Java VM as well, but what on
earth
was going through the head of the person who decided it would be a good
idea
to take down the calling native application as well????? (Which it doesn't
do cleanly anyway, it crashes in _exit() in the C RTL when unwinding
something to do with thread local storage.)
Why don't just override the close handler a hide/minimize the Swing app?

btw I have found few articles about JNI which would be very useful for you:

http://www.javaworld.com/javaworld/jw-05-2002/jw-0510-integrate.html
http://www.javaworld.com/javaworld/jw-10-1999/jw-10-jni.html

I developed once precisely a MFC application that invoked Java objects yes
in that direction C++ calls Java, I followed a great tutorial that I am
still looking
for in my PC if I find it will email it to you ...

Regards,
Giovanni
 
A

Andrew McDonagh

Tim said:
OK, so a bit of reading around says you can't just copy jvm.dll into your
application's directory, it insists on being run from its installed
location. So, make jvm.dll's installed location the current directory when I
run my test app. At which point JNI_CreateJavaVM works.

BUT

(1) That's OK for me hacking around but obviously not useful for deployment,
when the user might have who-knows-which version of the JRE installed
who-knows-where. The installation process for my MFC app couldn't add the
location of jvm.dll to the path because it hasn't a clue where it is (even
if I wanted to mess with the user's path for such a small new feature of my
app, which I don't). How do people solve this one?

AND

(2) I can now run a method in my jar. Which creates a Swing GUI (I'll switch
that off in due course, but during development it's obviously helpful to see
whether the spawned Java app exists and is doing anything useful). But how
to close the spawned app?

(a) calling DestroyJavaVM() isn't helpful - it doesn't return - hints in the
documentation suggest that its probably waiting for all the threads in the
Java application to terminate, which they aren't going to; that's fair
enough I guess

(b) closing the Swing GUI in the normal way (click on the window close box)
ends up in a (Java) call of System.exit(0); which takes down the calling C++
application! No! No! Surely not! How could I possibly want that?? Closing
the Java application should take down the Java application, and I'm not too
bothered about whether it takes down the Java VM as well, but what on earth
was going through the head of the person who decided it would be a good idea
to take down the calling native application as well????? (Which it doesn't
do cleanly anyway, it crashes in _exit() in the C RTL when unwinding
something to do with thread local storage.)

Clearly there's a bit of a learning curve with this technology ... any help
would be most welcome :)

Tim,

the java installation, current and user home dirs (plus other
properties) are available to you from...

http://www.imsc.res.in/Computer/local/Docs/Java/essential/system/properties.html

likewise, JAVAHOME environment etc are available via C++

hth
 
C

Chris Uppal

Tim said:
(1) That's OK for me hacking around but obviously not useful for
deployment, when the user might have who-knows-which version of the JRE
installed who-knows-where. The installation process for my MFC app
couldn't add the location of jvm.dll to the path because it hasn't a clue
where it is (even if I wanted to mess with the user's path for such a
small new feature of my app, which I don't). How do people solve this one?

It's generally thought that the best way to deploy Java-based, or
Java-including, standalone apps is to include the JRE as part of your
deployment. If you do that then you can hardwire the DLL location.

If you don't want to do that, or if you want to give your users the option of
using their own installed JRE, then you can look in the registry. Sun Java
installations follow the pattern that
HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime
Environment\CurrentVersion
is the string name of the current version. "1.5" on my machine. Under
HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\<version>
you should find the JavaHome and the RuntimeLib.

There are other cross-refs between the registry entries which should be pretty
obvious if you have access to machine(s) with more than one JRE installled.
The JDK installations use similar pointers, but you probably won't want to use
them in this context.

Other vendors' JVMs may use similar -- but, of course, not /very/ similar --
patterns. E.g. both IBM and BEA do.

(b) closing the Swing GUI in the normal way (click on the window close
box) ends up in a (Java) call of System.exit(0); which takes down the
calling C++ application! No! No! Surely not! How could I possibly want
that?? Closing the Java application should take down the Java
application, and I'm not too bothered about whether it takes down the
Java VM as well, but what on earth was going through the head of the
person who decided it would be a good idea to take down the calling
native application as well?????

Fair question. When you get more used to JNI you'll come to hate the Sun
JVM/JNI programmers with a great passion.

For now, I think that ensuring that you set the JFrame's
setDefaultCloseOperation() to DISPOSE_ON_CLOSE (instead of EXIT_ON_CLOSE, or
whatever it's called) will probably do.

You /may/ be able to prevent the JVM killing the calling app by setting an exit
hook (part of JNI but I forget the API just for the minute). I've had no luck
with that myself -- it just deadlocks my application, but then my application
does some rather unusual things with threads, so that may not be the general
experience.

You /may/ be able to prevent it by setting a security policy that forbids calls
to System.exit() (and friends) but I haven't experimented with that myself.

A couple of other potential gotchas to watch out for.

Once you have closed down the JVM, you cannot start a new one from the same
application. So you just get one, and you have to make it last...

Sun's programmers are careless about the floating point exception flags. If
you are doing much/any floating point in your C/C++ application, then you
should watch out for the JVM crashing because makes assumptions about the
underflow/overflow environment that it will find itself in.

I /think/ there may be problems with the -Xcheck:jni flag in the `1.5.0 JVM.
That flag worked fine in the 1.4 series JVMs, and was very useful. But I've
found that turning it on with the 1.5.0 version causes the JVM to flag JNI
errors (and -- of course -- therefore kill my application instantly) when I'm
reasonably certain that I'm doing nothing wrong.

-- chris
 
T

Tim Ward

Chris Uppal said:
Fair question. When you get more used to JNI you'll come to hate the Sun
JVM/JNI programmers with a great passion.

Thanks for those comments (not of which I'd managed to find in the
documentation!).

Actually I've discovered that the bottom half of the protocol stack I need
*is* implemented in C++, it's just not switched on in my build of a shared
library. So I'll also be looking at simply re-implementing the application
layers in C++ and not using the Java app at all - sounds like this could be
easier to install and more stable.
 

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

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,818
Latest member
Brigette36

Latest Threads

Top