您的位置:首页 > 编程语言 > C语言/C++

Android-ndk编译C/C++遇到的问题

2018-01-19 18:38 453 查看

1. 感言

  在搭建完相关的Android-ndk环境之后,就开始了C/C++程序的移植工作了。在这过程中遇到了一些编译上的问题,解决这些问题的过程相对比较痛苦,总之就是网上各种资料的查找。这边主要是将这些问题记录起来,供自己或遇到相同问题的开发人员查阅。希望对大家有所帮助。

2. cannot use typeid with -fno-rtti

  在博主的项目中使用了Boost.Interprocess,用于跨平台的进程间通信。在用ndk-build编译的时候出现了下面相关的错误:

/home/huangjh/boost_lib/boost_qs04/boost_1_65/include/boost/interprocess/detail/in_place_interface.hpp: In constructor 'boost::interprocess::ipcdetail::placement_destroy<T>::placement_destroy()':
/home/huangjh/boost_lib/boost_qs04/boost_1_65/include/boost/interprocess/detail/in_place_interface.hpp:54:110: error: cannot use typeid with -fno-rtti
:  in_place_interface(::boost::container::container_detail::alignment_of<T>::value, sizeof(T), typeid(T).name())

/home/huangjh/boost_lib/boost_qs04/boost_1_65/include/boost/interprocess/segment_manager.hpp: In member function 'bool boost::interprocess::segment_manager<CharType, MemoryAlgorithm, IndexType>::destroy(boost::interprocess::segment_manager<CharType, MemoryAlgorithm, IndexType>::char_ptr_holder_t)':
/home/huangjh/boost_lib/boost_qs04/boost_1_65/include/boost/interprocess/segment_manager.hpp:534:23: error: cannot use typeid with -fno-rtti
( typeid(T).name(), m_header.m_unique_index , dtor, is_intrusive_t());
^
/home/huangjh/boost_lib/boost_qs04/boost_1_65/include/boost/interprocess/segment_manager.hpp: In member function 'std::pair<T*, typename boost::interprocess::segment_manager_base<MemoryAlgorithm>::size_type> boost::interprocess::segment_manager<CharType, MemoryAlgorithm, IndexType>::priv_find_impl(const CharType*, bool)':
/home/huangjh/boost_lib/boost_qs04/boost_1_65/include/boost/interprocess/segment_manager.hpp:721:49: error: cannot use typeid with -fno-rtti
ret = priv_generic_find<char> (typeid(T).name(), m_header.m_unique_index, table, sz, is_intrusive_t(), lock);

  出现错误“error: cannot use typeid with -fno-rtti”的原因是:编译器关闭了RTTI,我们需要打开RTTI。解决方法是在Application.mk文件中添加下面一行:

APP_CPPFLAGS := -fexceptions -frtti

3. 如何使用第三方静态库

  由于boost库大部分属于模板类,只需要包含相应的头文件就可以使用,需要编译成库再使用的不多。博主的项目中并没有使用到,这里我仅仅是为了测试自己编译出的boost,而写的一个测试代码进行测试的。
date_time库是boost中少数需要编译的库之一,这里我们就以这个库作为例子。
  我们先来看下boost::date_time的一个测试用例:
#define BOOST_DATE_TIME_SOURCE
#include <iostream>
#include <boost/date_time/gregorian/gregorian.hpp>

using namespace std;
using namespace boost::gregorian;

int main(void)
{
date d1 = from_string("2018-1-18");

cout << to_simple_string(d1) << endl;
cout << to_iso_string(d1) << endl;
cout << to_iso_extended_string(d1) << endl;
cout << d1 << endl;
return 0;
}
  date_time库是boost中少数需要编译的库之一,如果不包含相应的库,则编译不过。
huangjh@ubuntu:jni$ ndk-build
[armeabi-v7a] Compile++ thumb: boost_date_test <= boost_date_test.cpp
[armeabi-v7a] Executable     : boost_date_test
/home/huangjh/boost_lib/boost_qs04/boost_1_65/include/boost/date_time/date_formatting.hpp:44: error: undefined reference to 'boost::gregorian::greg_month::as_short_string() const'
/home/huangjh/boost_lib/boost_qs04/boost_1_65/include/boost/date_time/date_parsing.hpp:67: error: undefined reference to 'boost::gregorian::greg_month::get_month_map_ptr()'
collect2: error: ld returned 1 exit status
make: *** [/home/huangjh/android-ndk/android-ndk-r10b/samples/hello-jni/obj/local/armeabi-v7a/boost_date_test] Error 1
  我们修改对应的Android.mk.
LOCAL_PATH := $(call my-dir)

BOOST_INCLUDE_PATH      := /home/huangjh/boost_lib/boost_qs04/boost_1_65/include
BOOST_LIB_PATH          := /home/huangjh/boost_lib/boost_qs04/boost_1_65/lib

#添加静态库开始
include $(CLEAR_VARS)
LOCAL_MODULE            := boost_date_time_lib
LOCAL_SRC_FILES         := $(BOOST_LIB_PATH)/libboost_date_time.a
include $(PREBUILT_STATIC_LIBRARY)
#添加静态库结束

include $(CLEAR_VARS)

LOCAL_MODULE            := boost_date_test
LOCAL_SRC_FILES := boost_date_test.cpp
LOCAL_CPPFLAGS += -fexceptions

LOCAL_C_INCLUDES        := $(BOOST_INCLUDE_PATH)
#添加静态库开始
LOCAL_STATIC_LIBRARIES := boost_date_time_lib
#添加静态库结束

LOCAL_LDFLAGS += -pie -fPIE

include $(BUILD_EXECUTABLE)
  把boost::date_time静态库添加进来,在编译,就通过了。

4. 如何使用第三方的动态库

  博主的项目中需要依赖动态库libfuse.so。其实动态库和静态库的添加是类似的。只需要把上面的改成类似下面的就可以了:
. . .

include $(CLEAR_VARS)
LOCAL_MODULE            := fuse_lib_so
LOCAL_SRC_FILES         := $(FUSE_LIB_PATH)/libfuse.so
include $(PREBUILT_SHARED_LIBRARY)

. . .

LOCAL_SHARED_LIBRARIES := fuse_lib_so

. . .

5. 总结

  后续遇到问题会在更新。如果有什么疑问或问题可以评论或私信。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: