呼叫C++;来自Java的函数
这是我关于StackOverflow的第一篇文章。我正在做一个项目,我需要你在JNI的帮助。我被困在那里。。。我最近一直在阅读和尝试它,但仍然不知道如何使它工作呼叫C++;来自Java的函数,java,c++,eclipse,c++11,java-native-interface,Java,C++,Eclipse,C++11,Java Native Interface,这是我关于StackOverflow的第一篇文章。我正在做一个项目,我需要你在JNI的帮助。我被困在那里。。。我最近一直在阅读和尝试它,但仍然不知道如何使它工作 我在C++中创建了一个静态库(下面是伪代码): 我所需要的就是能够使用accessZ()函数将一些参数从Java传递到libXYZ 新编辑: public final class NativeClass { { System.loadLibrary("myLibrary"); } public native voi
我在C++中创建了一个静态库(下面是伪代码):
我所需要的就是能够使用accessZ()函数将一些参数从Java传递到libXYZ 新编辑: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();
};
您不能直接调用这样的函数,您将从JNI调用的函数必须具有特定名称和特定形式,并且必须由某个Java类中的成员函数表示。(另外,Java没有无符号整数,因此您的
uint8\u t
可能必须是char
或其他一些基本类型,同样地,您需要考虑在Java中什么将表示std::vector
)
accessZ()
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();
};
然后,您的myLibrary.cpp
必须包含
和“api.h”
,并包含一个与
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);
}
此函数将成为库的访问点,但随后可以执行任何它想做的操作,它可以创建对象,调用对象上的函数,甚至可能保持暂时状态,因为库将在调用之间保持运行。(不过,最好对传递给函数的状态对象进行操作。)库可能会向Java公开任意多个函数,如下所示
以下是我的命令行(适用于Linux):
您看过任何现有的jni教程吗?为什么你希望我们为你写下明确的东西。。。这已经被记录了无数次了?@GhostCat:我当然看过JNI教程了。但是,它们都是用C++编写的特定函数,而不是函数库中的函数。在那里使用C++函数…不是存储在某个库或dll中-它们只是生活在某个真空中?!非常感谢您的评论和时间。。。我对JNI完全陌生。所以,如果你知道/有一些有用的链接/教程(不像HelloWorld JNI示例)来解决我的问题,请把它放在那里;也许,我错过了一些搜索结果。。。否则,我没有时间去讨论无用的讨论……你必须告诉我们你尝试了什么,也就是说,调用C++函数的java代码。作为建议,最好从一个非常简单的函数开始实验,比如
intgetint(){return 123;}
。否则,我们不清楚您希望我们给出什么样的答案,不会复制大量现有的关于JNI的免费在线教程或教科书章节。请记住,堆栈溢出与特定问题有关。你也不应该听起来那么苛刻。我是说,“我需要直接的回答”,来吧。。。这可不是你付钱给我们的。嗨@Vee,非常感谢你的回复。今天晚些时候(如果我有时间)我会试试,然后再给你回复。实际上,在这期间,我只需要将参数从java传递到C++,其中访问()函数返回空(即,空)。稍后,当我完成这个步骤(java -C++通信)时,我希望Access()返回布尔值;但现在我只关注问题的一部分。干杯。@M_Square我的代码包含一些错误。我现在测试并修复了它们,所以请尝试使用新版本。非常感谢您的努力。我昨天尝试过(多次使用不同的设置)用javah编译,但是上面提供的类没有编译。。。当我运行javah-jni NativeClass.java
时,我遇到了以下错误:线程“main”java.io.IOException中的异常:在java.net.URLClassLoader{url=[文件:/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre/lib/rt.jar],parent=gnu.gcj.runtime.SystemClassLoader{URL=[文件:./],parent=gnu.gcj.runtime.ExtensionClassLoader{url=[],parent=null}}}}在gnu.classpath.tools.javah.Main.getClass(libgcj tools.so.16)在gnu.classpath.tools.javah.Main.parseClasses(libgcj tools.so.16)在gnu.classpath.tools.javah.Main.Main(libgcj tools.so.16)运行(libgcj tools.so.16)
有什么想法吗?BR@M_Square这是个奇怪的名字,NativeClass/java.class
。这是一个“未找到文件”错误,与文件中的内容无关。编译其他类没有问题吗?您是否有NativeClass
遵循相同的文件命名条件?如果它是包x.y.z
中的公共类,则需要在名为x/y/z/NativeClass.java
的文件中找到它。(另外,C方法的名称是Java_x_y_z_NativeClass_accessZ
)在我的示例中,它不在任何包中。
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();
};
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);
}
NativeClass.INSTANCE.accessZ((char)10, "abc", new char[]{3, 5, 7});
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)