我正在尝试开发使用LibEvents的android native胶水应用程序。
我从这里获得了一个LibEvents的android友好版本...
https://github.com/ventureresearch/libevent
我的android.mk文件几乎完全相同(相对路径除外)。
它可以成功编译为静态库,并链接到我自己的共享库中。
但是,当我尝试执行时,从Dalvik收到错误消息,指示它无法加载我的共享库。
E/AndroidRuntime(16123): Process: com.marty.socketclient1, PID: 16123
E/AndroidRuntime(16123): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.marty.socketclient1/android.app.NativeActivity}: java.lang.IllegalArgumentException: Unable to load native library: /data/app-lib/com.marty.socketclient1-1/libSocketClient1.so
如果我不使用自己的LibEvents版本,则本机代码可以正常运行。
还要注意,如果我从LibEvents中删除所有现有的源文件,并使用自己的函数添加一个新模块,然后在共享库中调用它,那么一切都会正常进行。
这使我相信它是正确构建的(或者至少编译/链接标志本身并不禁止加载)。
ndk-depends 报告没有其他共享对象依赖关系,因此我认为在dlopen执行时,LibEvents中可能正在执行某些错误代码。
我尝试用Android日志记录替换LibEvents日志记录机制,但没有任何进一步的输出。
我也找不到任何发生的情况
__attribute__((__constructor__))
要么
_init
在LibEvents源代码中。
请注意,LibEvents只是“C”库,因此不能像C++那样具有静态初始化的对象(或者在这种假设下我错了吗?)。
我是否还没有其他在加载时执行功能的方法?
有什么想法我接下来可以检查吗?
我是否可以启用其他日志记录选项,从而提供进一步的见解?
我也将android.mk文件(如下所示)精简到了最小,以便我可以调用:
evutil_make_socket_nonblocking()
并且仍然遭受无法加载库的问题。
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libevents
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := \
../evutil.c \
../event.c \
../log.c \
../evthread.c \
../evmap.c \
../signal.c \
../epoll.c \
../poll.c \
../evutil_rand.c \
../select.c
LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
$(LOCAL_PATH)/../android \
$(LOCAL_PATH)/../include
LOCAL_CFLAGS := -DHAVE_CONFIG_H -DANDROID -fvisibility=hidden
#LOCAL_CFLAGS := -DHAVE_CONFIG_H -DANDROID -DNDEBUG -fvisibility=hidden
include $(BUILD_STATIC_LIBRARY)
最佳答案
万一其他人遇到此问题,这是解决方案。
这是一个漫长的过程,但是我仅对功能和隔离的模块进行了存根,直到仅用一个源文件即可重现该问题。
然后我注释掉代码,直到找到导致我的库无法加载的错误调用。
原来是这个...
long _evutil_weakrand(void)
{
return random();
}
实际上,如果我创建了任何调用random()的函数,则共享对象将无法加载。
显然,这与android级别有关。您需要使用19级,我正在使用21级。
与此相关...
Android NDK: load_library: cannot locate srand