This is my first post on StackOverflow. I am working on a project and I need your help in JNI. I got stuck there... I have been reading and trying it a lot recently, but still didn't figure out how to make it work.
I have created a static library in C++ (a pseudo-code is shown below):
// file: X.h
class X {
public:
X() {};
~X() {};
void fooX() { // do stuff };
void barX() { // do more stuff };
}
// file: X.cpp
#include "X.h";
// file: Y.h
#include "X.h"
class Y {
public:
Y() {x = new X()};
~Y() {};
fooY() { // do stuff };
barY() { // do more stuff };
private:
X x; // object of class X
}
// file: Y.cpp
#include "Y.h"
// file: Z.h
#include "Y.h"
class Z {
public:
Z(uint8_t, std::string, std::vector<uint8_t>);
~Z() {};
fooZ() { // do stuff };
barZ() { // do more stuff };
private:
Y y; // object of class Y
}
// file: Z.cpp
#include "Z.h"
Z::Z(uint8_t a, std::string b, std::vector<uint8_t> c)
{
/// do stuff and create an object of Y
Y y = new Y();
}
// file api.h
#include "Z.h"
void accessZ(uint8_t, std::string, std::vector<uint8_t>);
// file api.cpp
#include "api.h"
void accessZ(uint8_t a_uint,
std::string b_string,
std::vector<uint8_t> c_vector)
{
// create object of Z
Z z = new Z(a_uint, b_string, c_vector);
z->fooZ();
delete z;
z = NULL;
}
Further, I have compiled all of the above code as a static library (libXYZ.a) in C++ (Eclipse C++ CDT on Windows 7 using MinGW).
Now, what I would like to have is to be able to call the API accessZ() C++ function from a Java application! In other words, I have implemented the core functionality in C++ and I would like to implement the GUI in Java. Therefore, I need to access the C++ functions from the Java GUI...
How can I do that? I need direct answers and not vague ones please...
Your help is very appreciated.
Thanks a lot in advance for your support.
Edited
My project is as follows:
MyLibrary
|
Makefile header/ source/ bin/ object/ lib/
X.h X.cpp X.o libXYZ.a
Y.h Y.cpp Y.o
Z.h Z.cpp Z.o
api.h api.cpp api.o
All what I need is to be able to pass some parameters from Java to libXYZ using the accessZ() function.
New Edit:
public final class NativeClass {
{
System.loadLibrary("myLibrary");
}
public native void accessZ(char a_uint, String b_string, char[] c_vector);
public static final NativeClass getInstance() {
return INSTANCE;
}
private static final NativeClass INSTANCE = new NativeClass();
};
You can't call a function like this directly, the function you will call from JNI will have to have a particular name and a particular form and will have to be represented by a member function in some Java class. (Also, Java does not have unsigned integers, so your uint8_t
would have to be probably char
or some other primitive type, and similarly you'll need to think what will represent the std::vector
in Java.) But it's perfectly OK to
make the Java function publicly accessible (unfortunately, it can't be static, a class instance is important),
have the native implementation do nothing else than extract the parameters and call accessZ()
.
Typically, your code will look something like
public final class NativeClass {
{
System.loadLibrary("myLibrary");
}
public native void accessZ(char a_uint, String b_string, char[] c_vector);
public static final NativeClass getInstance {
return INSTANCE;
}
private static final NativeClass INSTANCE = new NativeClass();
};
Then your myLibrary.cpp
will have to include <jni.h>
and "api.h"
and to contain a function along the lines of
JNIEXPORT void JNICALL Java_NativeClass_accessZ(JNIEnv *env, jobject obj, jchar ja_uint, jstring jb_string, jcharArray jc_vector) {
uint8_t a_uint = (uint8_t)ja_uint;
const char *cfn = env->GetStringUTFChars(jb_string, 0);
std::string b_string{cfn};
env->ReleaseStringUTFChars(jb_string, cfn);
size_t sz = env->GetArrayLength(jc_vector);
std::vector<uint8_t> c_vector(sz);
jchar *c_array = env->GetCharArrayElements(jc_vector, NULL);
for(size_t i = 0; i < sz; i++)
c_vector[i] = c_array[i];
env->ReleaseCharArrayElements(jc_vector, c_array, 0);
accessZ(a_uint, b_string, c_vector);
}
wrapped in an extern "C"
block. Your JNI tutorial will tell you how to go about making a dynamic library out of it and helping Java find it. Just link the other parts of your project ( libXYZ.a
) with it statically when creating the .dll
(ie, list the archive among the sources). You can then call from within Java for example:
NativeClass.INSTANCE.accessZ((char)10, "abc", new char[]{3, 5, 7});
This function will become the access point of your library but then can do whatever it wants, it can create objects, call functions on them, it may even keep a transient state because your library will keep running between the calls. (It's better to operate on a state object passed to the function, though.) There may be arbitrarily many of functions exposed by the library to Java like this.
Here are my command lines (for Linux):
g++ -isystem /usr/java/jdk1.8.0_101/include/ -isystem /usr/java/jdk1.8.0_101/include/linux myLibrary.cpp -c -fPIC
(creates myLibrary.o)
g++ myLibrary.o libXYZ.a -shared -o libmyLibrary.so
(creates libmyLibrary.so)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.