Can't create shared library with static inside

隐身守侯 提交于 2019-11-28 11:46:27

Here is what I did to build the code successfully:

  1. In your Eclipse Android Project create the folder jni.

  2. Add the files calc_mean.c; calc_mean.h; Test_Library.c and Android.mk to the jni folder

  3. Remove the line #include "Test_Library.h"from the Test_Library.c file. Everything else can stay as it is.

  4. In the cygwin command line go to the root folder of your Eclipse Android project and run ndk-build

If you want to build your calc_mean also as static library during the ndk-build process then you can change your Android.mk file as follows:

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)

As I suppos the main reason was compiler settings, I make some modifications in makefile and my .a archive linked to shared library, here are modifications.

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

Simply use C compiler instead!

You compile with C++ compiler (Makefile has "$(GPP) -c *.c") and the function symbol name includes parameter information and is called different: not "mean", but something more complex, similar as Java names symbols internally. You can use "nm" to see what's inside an object file.

For example my g++ generates:

# nm x.o
00000000 T _Z4meanii

So there is no "mean" (but "Z4meanii"). Using a C compiler, and the symbol names are straightforward:

# nm x.o
00000000 T mean

(Please note that the same source code content was compiled)

So change in you Makefile:

obj:
    $(GCC) -c *.c

If for some reason a C++ compiler must be used, then extern "C" must be added:

calc_mean.h (simplified, without inclusion guards etc.)

#ifdef __cplusplus
extern "C" {
#endif

int mean(int, int);

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

In general, if you need C symbol names in C++ files, use extern "C". Test_Library.h uses it correctly and provides a nice example. You can put the same extern "C" logic (best including if #ifdef __cplusplus block) to your header file. Some consider it good practice to always do so.

But note that there are several, sometimes subtle, differences between C and C++, so I recommend to compile C sources with C compiler, although I know that there can be advantages using a C++ compiler.

oki,

Steffen

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!