JNI: instace object C++ from Java

F

flack

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!
 
G

Gordon Beaton

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
 
G

Gordon Beaton

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
 
R

Roedy Green

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
 
R

Roedy Green

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.
 
G

Gordon Beaton

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
 
R

Roedy Green

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.
 
U

unodivoi

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!!!!!
 
G

Gordon Beaton

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
 
F

flack

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!
 
F

flack

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);

}
 
U

unodivoi

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"
 
G

Gordon Beaton

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
 
G

Gordon Beaton

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
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top