Интеграция работы с нативным кодом на С/С++ для android в Eclipce (на примере, под Ubuntu). — часть 1

Создание проекта.

1)Необходимо добавить путь к директории с ndk в переменные среды, без этого все дальнейшее бесполезно.
2)Для создания андроид проекта с нативным кодом на С и С++ необходимо учесть несколько важных следующих замечаний (в качестве рекомендаций, можно и без них, но будет сложнее):

Расположение папки workspace для Eclipce должно быть таким, чтобы ndk имел права записи в эту папку и мог изменять свойства файлов расположенных в этой папке. То есть например чтобы папка с ndk и папка  workspace находились в домашней директории пользователя, а не на смонтированном носителе.
Крайне желательно чтобы пути к SDK, NDK и проекту содержали только латинские символы без пробелов.
Версия ndk желательна выше 5. В этом случае вы без особого труда сможете использовать stdlib

В случае если Вы собираетесь отлаживать нативный код:

Target SDK версия для проекта должна быть не меньше 9

 android:minSdkVersion="9"

В AndroidManifest.xml должен быть установлен флаг

 android:debuggable="true"

3)Необходимо установить CDT(C and C++ Development Tools) для Eclipce. Help->Install New Software выбираем репозиторий Вашей версии Eclipce(например Helios — http://download.eclipse.org/releases/helios) в ней Programming Languages и в ней C and C++ Development Tools.

4) Следующим шагом нам необходимо сконвертировать Ваш уже созданый андроид проект в совместный проект Java и C++. Нажимаем на проекте правой кнопкой New->Other (или Ctrl+n) и в открывшемся окне выбираем Convert to C/C++ Project жмем Next

на втором шаге выбираем Makefile project->—Other Toolchain—

Жмем Finish и в консоли Eclipce видим ошибку: «**** Build of configuration Default for project NativeExample **** make all make: *** Нет правила для сборки цели `all’. Останов.»
Все правильно — среда не видит ни правил сборки нативного кода ни самого кода.

5)Работа с JNI: Создадим класс- обертку для вызова наших нативных функций.

package com.example;
public class NativeLib {
	static{
		System.loadLibrary("native_lab");
	}
	public native String function(byte[] string);
}

Создаем папке проекта папку jni. В ней будет находится весь код на С и С++ и правила сборки. Переходим в деррикторию bin нашего проекта и выполняем из терминала следующую команду javah -jni com.example.NativeLib, которая генерирует заголовочный файл вызова Ваших нативных функций для С в соответствии с правилами JNI.

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_NativeLib */

#ifndef _Included_com_example_NativeLib
#define _Included_com_example_NativeLib
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_NativeLib
 * Method:    function
 * Signature: ([B)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_NativeLib_function
  (JNIEnv *, jobject, jbyteArray);

#ifdef __cplusplus
}
#endif
#endif

Переносим сгенерированный h файл в директорию jni. Осталось добавить только реализацию на С нашей функции в новом файле (например native.cpp):

#include <cstdlib>
#include "android_log.h"
#include "com_example_NativeLib.h"

jstring JNICALL Java_com_example_NativeLib_function
  (JNIEnv * env, jobject obj, jbyteArray string){

	// get "string" from JVM
	const size_t STRING_LENGTH = env->GetArrayLength(string);
	char * buffer = new char[STRING_LENGTH];
	env->GetByteArrayRegion(string, 0, STRING_LENGTH, (jbyte*) buffer);
	env->ReleaseByteArrayElements(string, (jbyte*) buffer, 0);

	LOGI(buffer);

	jstring result = env->NewStringUTF("done");
	return result;
}

6)Создаем правила сборки С/С++ библиотеки, для этого необходимо создать два мейкфайла Application.mk Android.mk в папке jni. Первый отвечает за общую сборку, второй за сборку модулей.

Application.mk:

# как будет оптимизироватся библиотека
#APP_OPTIM := debug

# подключение stllib 
#only if you platform upper then 2.2
#APP_STL :=gnustl_static 
# platform 1.6
APP_STL :=stlport_static

# библиотека которую собираем
APP_MODULES := native_lab

Android.mk:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
# библиотека которую собираем
LOCAL_MODULE    := native_lab
# исходные файлы через пробел
LOCAL_SRC_FILES := native.cpp
# библиотека для работы с логом андроида 
LOCAL_LDLIBS := -llog

include $(BUILD_SHARED_LIBRARY)

7)Пишем в лог андроида. Для удобства создадим заголовочный файл android_log.h следующего вида:

#include <android/log.h>

#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "NativeExample native",__VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG  , "NativeExample native",__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO   , "NativeExample native",__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN   , "NativeExample native",__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR  , "NativeExample native",__VA_ARGS__)

Пример использования виден выше в native.cpp.

Продолжение следует… 😉

Реклама

Детали luchaninov
небритый темный и злой - иногда

7 Responses to Интеграция работы с нативным кодом на С/С++ для android в Eclipce (на примере, под Ubuntu). — часть 1

  1. 1 says:

    А root для отладки нативного кода на телефоне нужен?

  2. Сергей says:

    А куда надо добавить jni.h, чтобы эклипс не подсвечивал его? Вроде и без него все собирается, но все же как-то в глаза бросается.

    мануал отличный, сэкономил много времени, автору спасибо)

  3. luchaninov says:

    В глаза он не бросается 😉 jni.h — это описание типов данных виртуальной машины java для С/С++, поэтому если вы его не пропишите, то код для передачи данных в JVM у Вас не заработает — так что не советую

  4. Serge Ivanov says:

    А что означает, когда gdb говорит, что моя функция not defined? Ну, и соответственно, в дебаг не перекидывает тоже.

    • luchaninov says:

      Надо код смотреть, скорее всего — или пакет забыли указать или синтаксическая ошибка в имени. Больше на вскидку пока ничего не приходит.

  5. Serge Ivanov says:

    Вообще, я название функции скопировал из полученного h-файла. Так же, библиотека подгружается, и до некоторого момента исполняется, по крайней мере, я вижу то, что пишется в лог из той функции.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: