I'm a newby about JNI.
I have an application write in C++ and I have to migrate it to Java.
I have seen that JNI permit to call c++ methods that return only
primitive type as string or int.
My question is simple: if I have a C++ class that we call "ClassA", can
I instance an object "ClassA" in Java that run the constructor and
where can I call the methods of "ClassA" as I was in C++?
I want something like this in Java:
jClassA a;
jClassB b
b = h.methodClassA(int d);
Can I do that?
Thank you!
> I have an application write in C++ and I have to migrate it to Java.
> I have seen that JNI permit to call c++ methods that return only
> primitive type as string or int.
Not just primitives: you can pass *any* Java types (primitives or
Objects) between Java and native code. Please note that String is not
a primitive.
> My question is simple: if I have a C++ class that we call "ClassA",
> can I instance an object "ClassA" in Java that run the constructor
> and where can I call the methods of "ClassA" as I was in C++?
No. JNI doesn't let you invoke arbitrary methods written in C or C++,
or create C++ objects.
JNI is a mechanism that lets you implement some (or all) of a Java
class's methods in C or C++. Furthermore those methods must have been
written with the intent of being called through JNI, i.e. they must
use signatures and data types as defined by JNI, and follow a specific
calling convention.
However from those native methods you are free to create C++ objects
and invoke their methods however you like.
JNI also lets your native code invoke any Java methods or
constructors, or access fields in Java objects.
/gordon

Signature
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
flack - 21 Mar 2006 18:49 GMT
Are you sure that there isn't some trick to use c++ methods?
The doubt is coming when I have read this post:
http://groups.google.it/group/comp.lang.java.programmer/browse_thread/thread/b4b
fa7d78f205066/3ac2b31639123573?lnk=st&q=instance+c%2B%2B+object+in+java+jni&rnum
=19&hl=it#3ac2b31639123573
What do you think about that?
Gordon Beaton - 21 Mar 2006 19:02 GMT
> Are you sure that there isn't some trick to use c++ methods?
Did you actually read the thread you referred to?
The example shows that it is possible to call a native method, and
_from_there_ create the C++ object. If you read my earlier answer,
you'll see that this is exactly what I said you must do.
The only "trick" here is that the C++ pointer is passed back to Java
as an int (although I would recommend a long).
You still can't use the object from Java. To do anything meaningful
with it you must first pass it back to a native method, then cast it
to whatever object it once was.
/gordon

Signature
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
Roedy Green - 21 Mar 2006 19:20 GMT
>No. JNI doesn't let you invoke arbitrary methods written in C or C++,
>or create C++ objects.
More precisely, from Java you cannot create arbitrary C or C++
objects, but of course you can create them on the C++ side.

Signature
Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.
Gordon Beaton - 21 Mar 2006 20:02 GMT
> More precisely, from Java you cannot create arbitrary C or C++
> objects, but of course you can create them on the C++ side.
Which is exactly what I wrote a couple of sentences later.
/gordon

Signature
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
Roedy Green - 21 Mar 2006 23:40 GMT
>Which is exactly what I wrote a couple of sentences later.
I thought your explanation was going over OP's head. So I decided to
restate it in a more elementary way.

Signature
Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.
unodivoi - 27 Mar 2006 02:19 GMT
First, thanks to all for response.
I haven't understand how I can manage the object pointer.
Can someone do an explicit example?
We can suppose that we have in java this code:
public class JObject {
private final long objectPtr = 0;
private native void objectCreate();
public static void main(String[] args){
JObject my = new JObject();
my.objectCreate();
}
}
In native code what will we write?
JNIEXPORT void JNICALL
Java_objectManager_objectCreate(JNIEnv *env, jobject obj)
{
CppObject *ptr = 0;
CppObject myCppObject;
ptr = &myCppObject;
?????????????????? :-(
}
Can someone rewrite correctly the above code with the target to
instance a C++ class (CppObject) and return to Java its pointer?
Thank you!!!!!
Gordon Beaton - 27 Mar 2006 09:30 GMT
> Can someone rewrite correctly the above code with the target to
> instance a C++ class (CppObject) and return to Java its pointer?
It's trivial if you declare the native method so that it *returns* the
long:
private native long objectCreate();
Then:
return (jlong)&myCppObject;
/gordon

Signature
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
flack - 27 Mar 2006 14:09 GMT
> private native long objectCreate();
>
> Then:
>
> return (jlong)&myCppObject;
Ok, this cast is simple.
But suppose that I must call a method of my object.
I have to call in java a function that give as member the long variable
pointer:
private native void objectMethodA(objectPtr);
public class JObject {
private final long objectPtr = 0;
private native long objectCreate();
private native void objectMethodA(long objectPtr);
public static void main(String[] args){
JObject my = new JObject();
my.objectCreate();
my.objectMethodA(objectPtr);
}
}
Then, how can I call "methodA" (myCppObject.methodA) in native code?
JNIEXPORT jlong JNICALL
Java_objectManager_objectMethodA(JNIEnv *env, jobject obj, jlong ptr)
{
????????????????????
}
JNIEXPORT jlong JNICALL
Java_objectManager_objectCreate(JNIEnv *env, jobject obj)
{
CppObject *ptr = 0;
CppObject myCppObject;
ptr = &myCppObject;
return (jlong)&ptr;
}
Thanks!
Gordon Beaton - 27 Mar 2006 14:52 GMT
> Then, how can I call "methodA" (myCppObject.methodA) in native code?
Obviously you have to cast the object back:
myCppObject = (CppObject*)ptr;
/gordon

Signature
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
flack - 30 Mar 2006 22:56 GMT
Java console give me this error: unsatisfiedLinkError:
JAxObjectManager.axObjectManagerConstructor() ect.....
I don't understand where is the error..
can someone help me?
I use:
- jvm--> j9 ibm
- pocket pc 2003
- evc4
I use this link:
255#"\Programmi\J9\MIDP20\bin\j9.exe"
"-jcl:midp20:loadLibrary=AxomStudentVCEmbeddedDLL"
"-Xbootclasspath:\Programmi\J9\MIDP20\lib\jclMidp20\jclMidp20.jxe"
"-cp" "\Programmi\J9\MIDP20\examples\Axom2\axom.jar" "JAxObjectManager"
--------------------------------
--------------------------------
class JAxObjectManager {
// salvo il puntatore all'oggetto allocato nel codice nativo
private static long axObjectManagerPtr = 0;
private native long axObjectManagerConstructor();
private native void jgetRootIndex(long axObjectManagerPtr);
public static void main(String[] args){
JAxObjectManager my = new JAxObjectManager();
axObjectManagerPtr = my.axObjectManagerConstructor();
my.jgetRootIndex(axObjectManagerPtr);
//System.out.println("Dopo: "+axObjectManagerPtr);
}
}
--------------------
--------------------
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JAxObjectManager */
#ifndef _Included_JAxObjectManager
#define _Included_JAxObjectManager
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JAxObjectManager
* Method: axObjectManagerConstructor
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_JAxObjectManager_axObjectManagerConstructor
(JNIEnv *, jobject);
/*
* Class: JAxObjectManager
* Method: jgetRootIndex
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_JAxObjectManager_jgetRootIndex
(JNIEnv *, jobject, jlong);
#ifdef __cplusplus
}
#endif
#endif
--------------------
--------------------
#define WIN32
#include <jni.h>
#include "windows.h"
#include <iostream>
#include <sstream>
#include <fstream>
#include <stdexcept>
#include <string>
#include <axom/axobjectmanager.h>
ect..... other include...
#include "JAxObjectManager.h"
JNIEXPORT jlong JNICALL
Java_JAxObjectManager_axObjectManagerConstructor(JNIEnv *env, jobject
obj)
{
AxObjectManager *axObjectManagerPtr = 0;
AxObjectManager myAxom;
axObjectManagerPtr = &myAxom;
return (jlong)axObjectManagerPtr;
}
JNIEXPORT void JNICALL
Java_JAxObjectManager_jgetRootIndex(JNIEnv *env, jobject obj, jlong
axObjectManagerPtrLong)
{
AxObjectManager* myAxom;
myAxom = (AxObjectManager*) axObjectManagerPtrLong;
//(myAxom).getRootIndex();
AxCommandExpand *beforeExpand = new
AxCommandExpand((*myAxom).getRootIndex());
(*myAxom).executeCommand(*beforeExpand);
TEST("expand (empty)",
beforeExpand->getChildrenIndexes().size()==0);
}
Gordon Beaton - 31 Mar 2006 08:32 GMT
> Java console give me this error: unsatisfiedLinkError:
> JAxObjectManager.axObjectManagerConstructor() ect.....
>
> I don't understand where is the error..
I don't know j9, but AFAICT you failed to load the DLL in your code
(i.e. System.loadLibrary() or equivalent).
/gordon

Signature
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
unodivoi - 31 Mar 2006 09:22 GMT
> I don't know j9, but AFAICT you failed to load the DLL in your code
> (i.e. System.loadLibrary() or equivalent).
i run dll "AxomStudentVCEmbeddedDLL" from link path, there isn't a
System.loadLibrary() in the code, it's not supported:
255#"\Programmi\J9\MIDP20\bin\j9.exe"
"-jcl:midp20:loadLibrary=AxomStudentVCEmbeddedDLL"
"-Xbootclasspath:\Programmi\J9\MIDP20\lib\jclMidp20\jclMidp20.jxe"
"-cp" "\Programmi\J9\MIDP20\examples\Axom2\axom.jar" "JAxObjectManager"
Gordon Beaton - 31 Mar 2006 12:17 GMT
> i run dll "AxomStudentVCEmbeddedDLL" from link path, there isn't a
> System.loadLibrary() in the code, it's not supported:
This article on using JNI with j9 seems to disagree with you:
http://www.cs.hku.hk/~fyp05016/kyng/ibm_j9.htm
Other posts I've seen claim that JNI itself isn't supported by early
versions of j9. Perhaps you need a later version that supports JNI and
thus has System.loadLibrary(). Again, I don't know j9 or midp...
Other things to check:
Is there (or has there been) a package declaration in your java
source? If so, there is a chance that the generated native symbol
names are wrong as a result.
Have you confirmed with a binary inspection tool that the native
symbols in the DLL *exactly* match those in the generated header file?
Failing that, post the complete and exact error message, it may
contain some more clues.
/gordon

Signature
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
>jClassA a;
>jClassB b
>b = h.methodClassA(int d);
Normally, Java calls C/C++, but you can do the reverse. Normally you
just pass primitives back and forth. On the C++ side, you can create a
Java object with the JNI API and populate its fields and return it,
most commonly a String.
You can also create C++ objects and use them on the C++ side. They
mean nothing on the Java side so you can't bring them over into Java
without converting them to Java objects first.
see http://mindprod.com/jgloss/jni.html

Signature
Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.