Я новичок в C ++ и JNI
Поток должен быть таким
Из Java я передаю пустой List
в JNI, JNI вызывает метод loadData(std::vector<int>)
из MyClass
, и этот метод заполняет мой список данными.
Итак, вопрос
У меня есть
class MyClass {
public:
MyClass();
~MyClass();
void loadData(std::vector<int> & vector);
};
void MyClass::loadData(std::vector<int> & vector)
{
const int size = 10;
vector.resize(size);
for (int i = 0; i < size; ++i) {
vector.push_back(4);
}
}
Это мой метод, который я написал на чистом C ++, и теперь мне нужно использовать его из Java, как это
public native void fillListWithData(List<Integer> list);
Итак, я написал такой метод в JNI, чтобы связать их
extern "C" JNIEXPORT void JNICALL
Java_com_google_ar_core_examples_java
_helloar_HelloArActivity_fillListWithData(
JNIEnv *env,
jobject /* this */,
jobject input
) {
myClass->loadData("HERE I NEED TO PASS MY " input);
}
И вот как я должен вызывать этот метод
public void TEST(){
List<Integer> list = new ArrayList<>();
fillListWithData(list);
Log.e("TAG", "HERE I NEED TO HAVE A LIST WITH FILLED DATA");
}
Я не могу понять, как передать этот список по ссылке JNI в C ++ ...
Любые идеи ценят
2 ответа
В этом случае все довольно просто. Все, что вам нужно сделать, это передать List
в ваш собственный код и заполнить его внутри JNI
части, используя методы доступа JNI
#include <vector>
#include "jni.h"
#include "recipeNo046_FillTheList.h"
using namespace std;
JNIEXPORT void JNICALL Java_recipeNo046_FillTheList_fillTheList
(JNIEnv *env, jclass cls, jobject obj) {
vector<int> vect { 1, 2, 3 };
jclass listClass = env->FindClass("java/util/List");
if(listClass == NULL) {
return; // alternatively, throw exception (recipeNo019)
}
jclass integerClass = env->FindClass("java/lang/Integer");
if(integerClass == NULL) {
return; // alternatively, throw exception (recipeNo019)
}
jmethodID addMethodID = env->GetMethodID(listClass, "add", "(Ljava/lang/Object;)Z");
if(addMethodID == NULL) {
return; // - || -
}
jmethodID integerConstructorID = env->GetMethodID(integerClass, "<init>", "(I)V");
if(integerConstructorID == NULL) {
return; // - || -
}
for(int i : vect) {
// Now, we have object created by Integer(i)
jobject integerValue = env->NewObject(integerClass, integerConstructorID, i);
if(integerValue == NULL) {
return;
}
env->CallBooleanMethod(obj, addMethodID, integerValue);
}
env->DeleteLocalRef(listClass);
env->DeleteLocalRef(integerClass);
}
Обратите внимание, что вам не нужно создавать List
объект внутри JNI
, как он у вас уже есть - внутри C++
кода. Он передается как аргумент метода native
.
Вы можете найти полный пример кода здесь:
https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo046
Запустив код, вы увидите, что данные из C++
передаются через объект List
.
> make test
/Library/Java/JavaVirtualMachines/jdk-12.0.1.jdk/Contents/Home/bin/java -Djava.library.path=:./lib -cp target recipeNo046.FillTheList
library: :./lib
1
2
3
Ответ, упомянутый @ Oo.oO, может показаться работающим в Windows 10, но не в случае с Windows 8.
Windows 8 не поддерживает контейнеры из библиотек Cpp для работы.
Сообщенная ошибка будет выглядеть так: «% 1 не является допустимым приложением Win32»
Это происходит во время работы Java-программы.
Файл DLL, созданный здесь, кажется, проблема.
Похожие вопросы
Новые вопросы
java
Java - это язык программирования высокого уровня. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег редко используется отдельно и чаще всего используется вместе с [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] и [maven].