I have class in C++ which must response for HTTP connection, that class must establish connection, send responses and do some other functions. This class is a part of huge project which I compile and finally get .so library for Android.
class HTTPSClient
{
public:
WinHTTPSClient();
~WinHTTPSClient();
bool Connect(const XMLString& a_strURL);
};
Now I want to call java functions from Connect function in c++. I have experiences in calling java functions from C++ code, but I always pass JavaVM to the class for example I call init(JavaVM* javaVm); and give as an argument javavm which comes from native code.
Now my question is: Can I call java method from C++ code without passing as an argument any JavaVm.
Define the JavaVM as a global/static variable of some class, e.g., by wrapping it up as a singleton. The variable can be accessed without explicitly passing it as an argument.
You can use the Java Invocation API to create a VM directly in your native code.
Jim S.
Related
I'm in trouble with this: http://imgur.com/hH0q3Tn
I'm using the VTK sample code and JNI isn't working and I don't know what to do. I compiled all the libraries and when I try the app on phone, the app stop.
What can I do?
Edit: Errors: http://pastebin.com/rf7vFVT8
The second arg for static native method should be jclass, not jobject.
See Are native Java methods equivalent to static Java methods? for more details.
Native Method Arguments
The JNI interface pointer is the first argument to native methods. The JNI interface pointer is of type JNIEnv. The second argument differs depending on whether the native method is static or nonstatic. The second argument to a nonstatic native method is a reference to the object. The second argument to a static native method is a reference to its Java class.
I solved.
The building of the library was incorrect and I followed this guide http://www.vtk.org/Wiki/VTK/Building/Linux
I'd like to pass C++ object from C++ to Java as function argument. I use SWIG to generate Java bindings for my class definition(named "MyObj"). I use the following method(env is a JNIEnv*),
env->CallStaticVoidMethod(cls, mid, my_obj);
where "cls" corresponds to a class I get via "env->FindClass" and "mid" points to a static method of it. When I run the program, however, in that method("mid") I found that my argument is just a null pointer.
I also tried to use (jobject)(&my_obj) but it also doesn't work. Did I miss something? Thanks so much!
In java, what does the private static method registerNatives() of the Object class do?
The other answers are technically correct, but not very useful for someone with no JNI experience. :-)
Normally, in order for the JVM to find your native functions, they have to be named a certain way. e.g., for java.lang.Object.registerNatives, the corresponding C function is named Java_java_lang_Object_registerNatives. By using registerNatives (or rather, the JNI function RegisterNatives), you can name your C functions whatever you want.
Here's the associated C code (from OpenJDK 6):
static JNINativeMethod methods[] = {
{"hashCode", "()I", (void *)&JVM_IHashCode},
{"wait", "(J)V", (void *)&JVM_MonitorWait},
{"notify", "()V", (void *)&JVM_MonitorNotify},
{"notifyAll", "()V", (void *)&JVM_MonitorNotifyAll},
{"clone", "()Ljava/lang/Object;", (void *)&JVM_Clone},
};
JNIEXPORT void JNICALL
Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
{
(*env)->RegisterNatives(env, cls,
methods, sizeof(methods)/sizeof(methods[0]));
}
(Notice that Object.getClass is not in the list; it will still be called by the "standard" name of Java_java_lang_Object_getClass.) For the functions listed, the associated C functions are as listed in that table, which is handier than writing a bunch of forwarding functions.
Registering native functions is also useful if you are embedding Java in your C program and want to link to functions within the application itself (as opposed to within a shared library), or the functions being used aren't otherwise "exported", since these would not normally be found by the standard method lookup mechanism. Registering native functions can also be used to "rebind" a native method to another C function (useful if your program supports dynamically loading and unloading modules, for example).
I encourage everybody to read the JNI book, which talks about this and much more. :-)
What might be slightly confusing is that the code shown for java.lang.Object.registerNatives in a previous answer is just an example of how to register native functions. This is the code that (in the implementation of OpenJDK) registers native functions for class Object. To register native functions for your own class, you must call the JNI function RegisterNatives from the native code in your own library. This might sound a bit circular, but there are a couple ways to break the loop.
Follow the example of this implementation of class Object:
a. In your Java class, declare a native method (preferably static) named registerNatives (or any other name. it doesn't matter).
b. In your native code, define a function named Java_<your fully qualified class name>_registerNatives, which contains a call to the JNI function RegisterNatives.
c. Make sure that in your Java code, your Java registerNatives method is called prior to any calls to other native methods.
OR
Use JNI_OnLoad
a. In your native library define a function jint JNI_OnLoad(JavaVM *vm, void *reserved). In the body of this function, call the JNI function RegisterNatives.
b. The Java VM will automatically look for and call JNI_OnLoad when your native library is loaded by System.loadLibrary, which you should already be calling, probably in a static initializer for your class. (You get the required env pointer by calling the GetEnv function in the table that the vm pointer points to.)
It is used on such scene :
C or C++ work as host, and Java the JVM as client. (C load jvm.dll and use JNI_CreateJavaVM to create a JVM)
When java code need to call host's C function,
If you still use jni dll (System.loadLibrary("foo.dll");) to bind the native java method, the memory space of dll is not the same as C host. (It still works if the function you called is host state irrelevant, but you cannot access host's state values in this way)
Here you need to use env->RegisterNatives() at host to inject(bind,expose,export) host's C functions to the JVM.
I'm currently using both C++ and Java in a project and I'd like to be able to send an object which is contained in C++ to my Java interface in order to modify it via a GUI and then send the modification back in C++.
So far I've been returning either nothing, an int or a boolean to Java via the JNI interface. This time I have to send an object through the interface. I have made similar class definition available both in C++ and in Java. I'd like to know how I'd go about creating the object so that I can use it in Java.
In C++ I have:
JNIEXPORT MyObject JNICALL Java_ca_X_Y_Z_C_1getMyObject(JNIEnv* env, jclass, jint number);
This function would get called by Java in order to get the object from the C++ side (the object is contained in a singleton, easily accessible).
On the Java end, I do a simple call to this method,
MyObject anObject = C_getMyObject(3);
which should return me the newly created object.
Java currently returns me a UnsatisfiedLinkError when I do the actual call. What is wrong?
Here's the solution I opted to use:
First, I would create a similar object in Java. Then, from C++ I would instanciate it and pass it all the values.
(C++)
clazz = env->FindClass("java/lang/Integer");
jmethodID method = env->GetMethodID(clazz, "<init>", "(I)V");
return env->NewObject(clazz, method, (jint)anInteger);
But then I realised this wasn't very portable and was a bit too complicated.
Instead, I decided to return a string that Java would parse and use to initialize the object on its side.
(JAVA)
String aString = "valuesoftheobject";
MyObject myObject(aString);
MyObject would have a constructor which takes a string. I believe the solution is simple and effective.
Another tool you should look at is SWIG. SWIG is a great tool for generate wrappers in other languages (such as Java, Python or C#) for existing C/C++ objects. It will generate automatic Java wrappers around C/C++ objects, and do all the heavy JNI lifting for you.
I use it extensively in Xuggler. To see an example, if you download the Xuggler source code there is a C++ object here:
csrc/com/xuggle/xuggler/IStreamCoder.h
I define a SWIG interface file here:
csrc/com/xuggle/xuggler/IStreamCoder.i
And when run through Swig it generates a Java object (which is stored here)
generate/java/com/xuggle/xuggler/IStreamCoder.java
We can then access that object from Java easily (well, I add some ref counting stuff, but that's pretty advanced). Hope that helps.
Art
If your MyObject class is defined in C++, you're not going to be able access its methods in Java. I'd try to define a Java wrapper class around your C object:
Java:
public C_Object() {
handle = createHandle();
}
private native long createHandle(); // or whatever pointer/handle type?
public void doStuff() {
_doStuff(handle);
}
private native void _doStuff(long handle);
If you can extrapolate a C api instead, you might try JNA.
Your UnsatisfiedLinkError may be the extra character in your function name as written above, or perhaps it can't handle the MyObject return value?
In java, what does the private static method registerNatives() of the Object class do?
The other answers are technically correct, but not very useful for someone with no JNI experience. :-)
Normally, in order for the JVM to find your native functions, they have to be named a certain way. e.g., for java.lang.Object.registerNatives, the corresponding C function is named Java_java_lang_Object_registerNatives. By using registerNatives (or rather, the JNI function RegisterNatives), you can name your C functions whatever you want.
Here's the associated C code (from OpenJDK 6):
static JNINativeMethod methods[] = {
{"hashCode", "()I", (void *)&JVM_IHashCode},
{"wait", "(J)V", (void *)&JVM_MonitorWait},
{"notify", "()V", (void *)&JVM_MonitorNotify},
{"notifyAll", "()V", (void *)&JVM_MonitorNotifyAll},
{"clone", "()Ljava/lang/Object;", (void *)&JVM_Clone},
};
JNIEXPORT void JNICALL
Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
{
(*env)->RegisterNatives(env, cls,
methods, sizeof(methods)/sizeof(methods[0]));
}
(Notice that Object.getClass is not in the list; it will still be called by the "standard" name of Java_java_lang_Object_getClass.) For the functions listed, the associated C functions are as listed in that table, which is handier than writing a bunch of forwarding functions.
Registering native functions is also useful if you are embedding Java in your C program and want to link to functions within the application itself (as opposed to within a shared library), or the functions being used aren't otherwise "exported", since these would not normally be found by the standard method lookup mechanism. Registering native functions can also be used to "rebind" a native method to another C function (useful if your program supports dynamically loading and unloading modules, for example).
I encourage everybody to read the JNI book, which talks about this and much more. :-)
What might be slightly confusing is that the code shown for java.lang.Object.registerNatives in a previous answer is just an example of how to register native functions. This is the code that (in the implementation of OpenJDK) registers native functions for class Object. To register native functions for your own class, you must call the JNI function RegisterNatives from the native code in your own library. This might sound a bit circular, but there are a couple ways to break the loop.
Follow the example of this implementation of class Object:
a. In your Java class, declare a native method (preferably static) named registerNatives (or any other name. it doesn't matter).
b. In your native code, define a function named Java_<your fully qualified class name>_registerNatives, which contains a call to the JNI function RegisterNatives.
c. Make sure that in your Java code, your Java registerNatives method is called prior to any calls to other native methods.
OR
Use JNI_OnLoad
a. In your native library define a function jint JNI_OnLoad(JavaVM *vm, void *reserved). In the body of this function, call the JNI function RegisterNatives.
b. The Java VM will automatically look for and call JNI_OnLoad when your native library is loaded by System.loadLibrary, which you should already be calling, probably in a static initializer for your class. (You get the required env pointer by calling the GetEnv function in the table that the vm pointer points to.)
It is used on such scene :
C or C++ work as host, and Java the JVM as client. (C load jvm.dll and use JNI_CreateJavaVM to create a JVM)
When java code need to call host's C function,
If you still use jni dll (System.loadLibrary("foo.dll");) to bind the native java method, the memory space of dll is not the same as C host. (It still works if the function you called is host state irrelevant, but you cannot access host's state values in this way)
Here you need to use env->RegisterNatives() at host to inject(bind,expose,export) host's C functions to the JVM.