请帮助我搜索整个互联网,但我找不到答案...
我创建了简单的函数int mean(int, int);
并将其放在 calc_mean.h 中并在 calc_mean.c 中初始化它是这两个文件。
#include "calc_mean.h"
int mean(int a, int b)
{
return (a+b) / 2;
}
int mean(int, int);
然后我使用以下make文件创建make文件并构建名为Test_Archive.a的存档(.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
default: all
all: obj
$(AR) r Test_Archive.a *.o
obj:
$(GPP) -c *.c
我获得 Test_Archive.a 存档文件。现在我想将这个存档文件添加到JNI并从我的JNI项目中调用mean
函数,因为我创建了JNI和Java文件,您可以在下面看到。
如何在java层中看到我有一个名为JMean
的本地方法的TestJavaClass,此方法有两个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头文件
/* 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
#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
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 Compile thumb:Test_Library&lt; = Test_Library.c SharedLibrary:libTest_Library.so C:/cygwin/home/android-ndk-r5b/Fido/ProjectOSTX/obj/local/armeabi/objs/OSTX_Library/OSTX_Library.o: 在函数
Java_com_Fido_OSTXLib_OSTX_JMean': C:/cygwin/home/android-ndk-r5b/Fido/ProjectOSTX/jni/OSTX_Library.c:6: undefined reference to
中,'collect2:ld返回1退出状态make: * [/home/android-ndk-r5b/Fido/ProjectOSTX/obj/local/armeabi/libOSTX_Library.so] 错误1
答案 0 :(得分:1)
以下是我成功构建代码所做的工作:
在Eclipse Android项目中创建文件夹jni
。
将文件calc_mean.c; calc_mean.h; Test_Library.c and Android.mk
添加到jni文件夹
从Test_Library.c文件中删除行#include "Test_Library.h"
。其他所有东西都可以保持不变。
在cygwin命令行中,转到Eclipse Android项目的根文件夹并运行ndk-build
如果您想在ndk构建过程中将calc_mean也构建为静态库,那么您可以按如下方式更改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)
答案 1 :(得分:1)
正如我所说的主要原因是编译器设置,我在 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
答案 2 :(得分:1)
只需使用C编译器!
使用C ++编译器编译(Makefile具有“$(GPP)-c * .c”),函数符号名称包含参数信息,称为不同:不是“mean”,而是更复杂,类似于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,
斯特芬