#java #android #c #android-ndk
#java #Android #c #android-ndk
Вопрос:
В настоящее время у нас есть некоторое программное обеспечение для обработки изображений, написанное на c , которое используется нашим приложением для IOS. Я пытаюсь интегрировать этот код обработки изображений в проект Android, который я создал с помощью Android NDK.
У меня есть мой проект Android и sdk, все настроено и готово к работе. У меня также есть настройка ndk и он готов к работе.
Я следовал этому руководству (что потрясающе), и я был озадачен той частью, в которой он определял код для native.c, потому что у него было такое имя функции,
void Java_com_mamlambo_sample_ndk1_AndroidNDK1SampleActivity_helloLog(JNIEnv * env, jobject this, jstring logThis)
Мне кажется, что мне нужно пройти через все мои существующие функции c и изменить код, чтобы NDK распознал его.
Итак, вот мои вопросы,
- Должен ли я изменять свой существующий код на c , чтобы он работал с ndk builder? И если да, то что мне нужно изменить в моем коде для этой работы?
- Есть ли способ получить Android.mk файл создает целый каталог? У меня много файлов, и я не хотел перечислять каждый из них, чтобы их собрать.
Ответ №1:
1) Вы должны иметь возможность создавать без изменений, но вам нужно будет написать некоторые из этих функций-оболочек JNI, чтобы вызвать их из Java. Надеюсь, у вас есть небольшое количество классов верхнего уровня, и вам нужно будет только обернуть их. Например. Вот что у меня есть для игры, которую я (медленно) пишу:
// android.cpp
#include "game.h"
#include <jni.h>
namespace {
Game* toGame(jlong gamePtr) {
return reinterpret_cast<Game*>(gamePtr);
}
}
extern "C" {
jlong Java_com_rarepebble_game3_Game_create(JNIEnv* env, jobject jobj) {
Game* g = new Game();
return reinterpret_cast<jlong>(g);
}
void Java_com_rarepebble_game3_Game_destroy(JNIEnv* env, jobject jobj, jlong gamePtr) {
delete toGame(gamePtr);
}
void Java_com_rarepebble_game3_Game_update(JNIEnv* env, jobject jobj, jlong gamePtr, jboolean isTouching, jfloat touchX, jfloat touchY) {
toGame(gamePtr)->update(isTouching, touchX, touchY);
}
void Java_com_rarepebble_game3_Game_render(JNIEnv* env, jobject jobj, jlong gamePtr) {
toGame(gamePtr)->render();
}
// ... and a few others. Only one class, though.
}
На стороне Java это позволяет мне объявлять эти функции в моем com.rarepebble.game3.Game
классе и вызывать их в соответствующие моменты жизненного цикла приложения. (Обратите внимание, как имена пакетов, классов и функций Java соответствуют именам функций в C ):
//Game.java
package com.rarepebble.game3;
// (imports)
public class Game {
static {
System.loadLibrary("game3lib");
}
// These are the functions you defined in C
private native long create();
private native void destroy(long gamePtr);
private native void update(long gamePtr, boolean isTouched, float x, float y);
private native void render(long gamePtr);
private long gamePtr = 0;
Game() {
gamePtr = create();
}
@Override
protected void finalize() throws Throwable {
if (gamePtr != 0) {
destroy(gamePtr);
}
super.finalize();
}
// etc...
}
2) Вы можете использовать
LOCAL_SRC_FILES := $ (подстановочный знак * .cpp) $ (подкаталог подстановочных знаков /*.cpp) #и т.д…
Редактировать: как и было запрошено, мой заголовок класса C Game, «game.h»:
// game.h
#ifndef GAME_INCLUDED
#define GAME_INCLUDED
// Various game and standard library includes.
// *NO* JNI or Android includes.
namespace game {
class Game {
public:
Game();
~Game();
void update(bool isTouching, float touchX, float touchY);
void render();
// other funcs...
private:
// etc...
};
}
#endif //def GAME_INCLUDED
Аналогично, «game.cpp » это тоже не включает в себя никаких материалов JNI.
Комментарии:
1. Большое спасибо за помощь, Мартин, эти примеры — одни из лучших, которые я видел из учебника по NDK. Итак, те функции, которые там называются как «Java_com_rarepebble_game3_Game_update», — это то, какими должны быть имена функций C ? Что-то вроде «Java_packages_function»?
2. Да, именно так. Все, что нужно после
Java_
, должно соответствовать полному имени пакета, класса и функции, которые вы хотите, чтобы они отображались как в Java. Вам нужно будет определить класс в Java и добавитьprivate native etc...
в него эти объявления. (Я редактирую свой ответ, чтобы сделать это более понятным.)3. Потрясающе, поэтому мне в основном нужно просмотреть все мои файлы на c и изменить имена, чтобы они соответствовали «Java_package_function». Кроме того, нужно ли включать файлы заголовков в сборку ndk? Или только .cpp-файлы?
4. Лично я бы рекомендовал добавить файл C , который просто перенаправляет вызовы в вашу существующую библиотеку. Это означает, что вы не загрязняете свою основную функциональность Java-материалами. Теоретически вы могли бы скомпилировать большую часть одного и того же кода как для Android, так и для iOS. Вы можете видеть, что я просто включаю свой «game.h» в приведенный выше пример, и ни один из остальных моих C -кодов не должен знать, что он вызывается из Java. Этот файл практически единственный в моей библиотеке, который включает jni.h. В моем случае у меня сборка Windows с использованием той же кодовой базы. Вам не нужно включать заголовочные файлы в makefile.
5. Огромное спасибо, Мартин! Вы избавили меня от МНОГИХ головных болей.