你是否代码中使用了Boost C++库? 你是否想轻松移植这些代码到Android? 或者你只是想使用Boost开始创建一个Android平台的新项目? 通过CrystaX NDK 10.1.0, 你就可以同时拥有Android原生开发套件和Boost C++库!
接下来看看如何实现.
首先我假设你使用标准的NDK build方式, 包括使用Application.mk和Android.mk文件. 以下是一个最简单的项目,只有native部分的运行程序:
. └── jni ├── Android.mk ├── Application.mk └── test.cpp
# Application.mk APP_ABI := all
# Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := test-boost LOCAL_SRC_FILES := test.cpp include $(BUILD_EXECUTABLE)
// test.cpp #include <iostream> int main() { return 0; }
现在来扩展成一个简单的Boost-enabled项目. 这里使用Boost序列化库示例; 其他库类似. 唯一区别是Android.mk中的引用库名称.
首先,添加源文件 (使用 official Boost example):
// gps.hpp #ifndef GPS_HPP_7D5AF29629F64210BE00F3AF697BA650 #define GPS_HPP_7D5AF29629F64210BE00F3AF697BA650 // include headers that implement a archive in simple text format #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> ///////////////////////////////////////////////////////////// // gps coordinate // // illustrates serialization for a simple type // class gps_position { private: friend class boost::serialization::access; friend std::ostream &operator<<(std::ostream &, gps_position const &); // When the class Archive corresponds to an output archive, the // & operator is defined similar to <<. Likewise, when the class Archive // is a type of input archive the & operator is defined similar to >>. template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & degrees; ar & minutes; ar & seconds; } int degrees; int minutes; float seconds; public: gps_position(){} gps_position(int d, int m, float s) : degrees(d), minutes(m), seconds(s) {} bool operator==(gps_position const &g) const { return degrees == g.degrees && minutes == g.minutes && seconds == g.seconds; } bool operator!=(gps_position const &g) const { return !(*this == g); } }; void save(gps_position const &g); void load(gps_position &g); #endif // GPS_HPP_7D5AF29629F64210BE00F3AF697BA650
// gps.cpp #include <fstream> #include "gps.hpp" const char *FILENAME = "gps.dat"; std::ostream &operator<<(std::ostream &s, gps_position const &g) { s << "GPS(" << g.degrees << "/" << g.minutes << "/" << g.seconds << ")"; return s; } void save(gps_position const &g) { // create and open a character archive for output std::ofstream ofs(FILENAME); boost::archive::text_oarchive oa(ofs); // write class instance to archive oa << g; // archive and stream closed when destructors are called } void load(gps_position &g) { // create and open an archive for input std::ifstream ifs(FILENAME); boost::archive::text_iarchive ia(ifs); // read class state from archive ia >> g; // archive and stream closed when destructors are called }
其次, 修改test.cpp做点实际的事情:
// test.cpp #include <iostream> #include <iomanip> #include "gps.hpp" int main() { // create class instance const gps_position g(35, 59, 24.567f); std::cout << "Initial value: " << g << std::endl; save(g); // ... some time later restore the class instance to its orginal state gps_position newg; load(newg); std::cout << "After load: " << newg << std::endl; if (g != newg) { std::cerr << "ERROR: Loaded object differs from the saved one" << std::endl; return 1; } std::cout << "Congratulations! GPS object was successfully saved and then loaded" << std::endl; return 0; }
最后,修改Android.mk包含以上文件,启用Boost Serialization:
# Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := test-boost LOCAL_SRC_FILES := test.cpp gps.cpp LOCAL_STATIC_LIBRARIES := boost_serialization_static # Or, if you need to link with Boost Serialization library dynamically: #LOCAL_SHARED_LIBRARIES := boost_serialization_shared include $(BUILD_EXECUTABLE) $(call import-module,boost/1.57.0)
现在这个示例项目如下所示:
. └── jni ├── Android.mk ├── Application.mk ├── gps.cpp ├── gps.hpp └── test.cpp
Ok, 完成了! 来看看如何编译运行. 注意这里ndk-build使用了APP_ABI参数armeabi-v7a; 只是示例,其他所有ABIs都一样可用.
$ ndk-build APP_ABI=armeabi-v7a [armeabi-v7a] Compile++ thumb: test-boost <= test.cpp [armeabi-v7a] Compile++ thumb: test-boost <= gps.cpp [armeabi-v7a] Prebuilt : libgnustl_shared.so <= <NDK>/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/thumb/ [armeabi-v7a] Executable : test-boost [armeabi-v7a] Prebuilt : libboost_atomic.so <= <NDK>/sources/boost/1.57.0/libs/armeabi-v7a/ [armeabi-v7a] Install : libcrystax.so => libs/armeabi-v7a/libcrystax.so [armeabi-v7a] Install : test-boost => libs/armeabi-v7a/test-boost [armeabi-v7a] Install : libgnustl_shared.so => libs/armeabi-v7a/libgnustl_shared.so $ adb push libs/armeabi-v7a/libcrystax.so /data/local/tmp 1231 KB/s (537036 bytes in 0.425s) $ adb push libs/armeabi-v7a/libgnustl_shared.so /data/local/tmp 1234 KB/s (718448 bytes in 0.568s) $ adb push libs/armeabi-v7a/test-boost /data/local/tmp 840 KB/s (50536 bytes in 0.058s) $ adb shell 'cd /data/local/tmp && LD_LIBRARY_PATH=/data/local/tmp ./test-boost' Initial value: GPS(35/59/24.567) After load: GPS(35/59/24.567) Congratulations! GPS object was successfully saved and then loaded
如你所见,不用修改任何代码就可用了 - 代码跟其他桌面和移动平台完全一样. 而且在所有平台的运行表现也一样. Android从2.3 (API level 9)开始支持.
印象深刻吧? 现在就来体验 CrystaX NDK 吧!