Как мне подготовить мои .cpp-файлы для Android ndk для их сборки?

#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 распознал его.

Итак, вот мои вопросы,

  1. Должен ли я изменять свой существующий код на c , чтобы он работал с ndk builder? И если да, то что мне нужно изменить в моем коде для этой работы?
  2. Есть ли способ получить 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. Огромное спасибо, Мартин! Вы избавили меня от МНОГИХ головных болей.