Невозможно создать общую библиотеку со статической внутренней - PullRequest
2 голосов
/ 07 сентября 2011

Пожалуйста, помогите мне выполнить поиск, бросьте весь интернет, но я не могу найти ответ ...

Слой

Я создал простую функцию int mean(int, int); и поместил ее в calc_mean.h и инициализируйте его в calc_mean.c вот эти два файла.

calc_mean.c

#include "calc_mean.h"

int mean(int a, int b)  
{  
return (a+b) / 2;  
}  

calc_mean.h

int mean(int, int);

Затем я создаю файл make и файл архива сборки (.a) с именем Test_Archive.a, используя следующий файл make

makefile

GCC := C:\Tools\ndk-toolchain\ndk-standalone\bin\arm-linux-androideabi-gcc.exe
GPP := C:\Tools\ndk-toolchain\ndk-standalone\bin\arm-linux-androideabi-g++.exe
AR  := C:\Tools\ndk-toolchain\ndk-standalone\bin\arm-linux-androideabi-ar.exe

default: all

all: obj
    $(AR) r Test_Archive.a *.o

obj:
    $(GPP) -c *.c

Я получаю Test_Archive.a архивный файл.Теперь я хочу добавить этот архивный файл в JNI и вызвать функцию mean из моего проекта JNI, для этого я создал файлы JNI и Java, которые вы можете увидеть ниже.


Слой JAVA

Как вы можете видеть здесь в слое Java У меня есть TestJavaClass, у которого есть один нативный метод с именем JMean, этот метод имеет два int аргумента и также возвращает int.

public class TestJavaClass
{
    /** Default Constructor
     * 
     */
    public TestJavaClass( ) {

    }

    /** Test Function. 
     *  
     * @param a
     * @param b
     * @return
     */
    public native int JMean( int a, int b);
}

Слой JNI

Это заголовочный файл JNI

Test_Library.h

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

#ifndef _Included_com_Fido_OSTXLib_OSTX
#define _Included_com_Fido_OSTXLib_OSTX
#ifdef __cplusplus
extern "C" {
#endif

/*
 * Class:     com_Fido_OSTXLib_OSTX
 * Method:    JMean
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_Fido_OSTXLib_OSTX_JMean
  (JNIEnv *, jobject, jint, jint);

#ifdef __cplusplus
}
#endif
#endif

Test_Library.c

#include "Test_Library.h"
#include "calc_mean.h"

JNIEXPORT jint JNICALL Java_com_Fido_OSTXLib_OSTX_JMean( JNIEnv* env, jobject thiz, jint a, jint b )
{
    return mean( a, b );
}

Я положил эти два файла Test_Library.h , Test_Library.c и calc_mean.h , Test_Archive.a и создайте файл make Android.mk

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE           := Test_Library
LOCAL_SRC_FILES        := Test_Library.c

LOCAL_LDLIBS := -LTest_Archive.a

include $(BUILD_SHARED_LIBRARY)

, но когда я хочу создать файл .so, возникает следующая ошибка, почему?

$ ../../ndk-build Компилировать большой палец: Test_Library <= Test_Library.c SharedLibrary: libTest_Library.so C: / cygwin / home / android-ndk-r5b / Fido / ProjectOSTX / obj/local/armeabi/objs/OSTX_Library/OSTX_Library.o: в функции <code>Java_com_Fido_OSTXLib_OSTX_JMean': C:/cygwin/home/android-ndk-r5b/Fido/ProjectOSTX/jni/OSTX_Library.c:6: undefined reference to mean 'collect2: ld вернул 1 состояние выхода make: * [/ home / android-ndk-r5b / Fido / ProjectOSTX /объект / местные / armeabi /libOSTX_Library.so] Ошибка 1

Почему неопределенная ссылка на `mean '?

Ответы [ 3 ]

1 голос
/ 09 сентября 2011

Поскольку я полагаю, что основной причиной были настройки компилятора, я вносил некоторые изменения в makefile и в мой .a-архив, связанный с общей библиотекой, вот модификации.

GCC := C:\Tools\ndk-toolchain\ndk-standalone\bin\arm-linux-androideabi-gcc.exe
GPP := C:\Tools\ndk-toolchain\ndk-standalone\bin\arm-linux-androideabi-g++.exe
AR  := C:\Tools\ndk-toolchain\ndk-standalone\bin\arm-linux-androideabi-ar.exe

OPTIONS  :=\
-fpic \
-ffunction-sections \
-funwind-tables  \
-fstack-protector \
-D__ARM_ARCH_5__ \
-D__ARM_ARCH_5T__ \
-D__ARM_ARCH_5E__ \
-D__ARM_ARCH_5TE__ \
-Wno-psabi \
-march=armv5te \
-mtune=xscale \
-msoft-float \
-mthumb \
-Os \
-fomit-frame-pointer \
-fno-strict-aliasing \
-finline-limit=64 \
-DANDROID \
-Wa, \
-O2 \
-DNDEBUG \
-g \

default: all


all: obj
    $(AR) r libtestlibrary.a *.o

obj:
    $(GCC) $(OPTIONS) -c *.c
1 голос
/ 09 мая 2012

Просто используйте вместо этого компилятор C!

Вы компилируете с компилятором C ++ (Makefile имеет "$ (GPP) -c * .c"), а имя символа функции включает информацию о параметрах иназывается по-другому: не «значит», но что-то более сложное, похожее на символы имен Java внутри.Вы можете использовать «nm», чтобы увидеть, что находится внутри объектного файла.

Например, my g ++ генерирует:

# nm x.o
00000000 T _Z4meanii

Так что «среднего» нет (но"Z4meanii").Используя компилятор C, имена символов просты:

# nm x.o
00000000 T mean

(Обратите внимание, что скомпилировано то же содержимое исходного кода)

Итак, измените ваш Makefile:

obj:
    $(GCC) -c *.c

Если по какой-то причине необходимо использовать компилятор C ++ , то необходимо добавить extern "C":

calc_mean.h (упрощенно, без защиты включения и т. д.)

#ifdef __cplusplus
extern "C" {
#endif

int mean(int, int);

#ifdef __cplusplus
} // extern "C"
#endif

В общем, если вам нужны имена символов C в файлах C ++, используйте extern "C".Test_Library.h использует его правильно и предоставляет хороший пример.Вы можете поместить ту же логику extern "C" (лучше всего, если блок #ifdef __cplusplus) в ваш заголовочный файл.Некоторые считают хорошей практикой всегда делать это.

Но учтите, что между C и C ++ есть несколько, иногда тонкие различия, поэтому я рекомендую компилировать исходники C с помощью компилятора C, хотя я знаю, что могут бытьПреимущества использования компилятора C ++.

oki,

Steffen

1 голос
/ 08 сентября 2011

Вот что я сделал, чтобы успешно построить код:

  1. В вашем проекте Eclipse Android создайте папку jni.

  2. Добавьте файлы calc_mean.c; calc_mean.h; Test_Library.c and Android.mk в папку jni

  3. Удалите строку #include "Test_Library.h" из файла Test_Library.c.Все остальное может оставаться как есть.

  4. В командной строке cygwin перейдите в корневую папку вашего проекта Eclipse Android и запустите ndk-build

Если вы хотите собрать свой calc_mean также как статическую библиотеку во время процесса ndk-build, вы можете изменить файл Android.mk следующим образом:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE           := Test_Archive
LOCAL_SRC_FILES        := calc_mean.c

# compiler flags.
LOCAL_LDLIBS   = -lz -lm
LOCAL_CFLAGS   = -Wall -pedantic -std=c99 -g

include $(BUILD_STATIC_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE := Test_Library
LOCAL_STATIC_LIBRARIES := Test_Archive
LOCAL_SRC_FILES := Test_Library.c


include $(BUILD_SHARED_LIBRARY)
...