CrystaX NDK中使用Boost C++库是一件非常简单的事情.
翻译自 https://www.crystax.net/en/blog/2
首先假设使用标准的NDK build方式, 包括Application.mk和Android.mk文件. 以下是一个最简单的项目,只有native部分的运行程序:
.
└── jni
├── Android.mk
├── Application.mk
└── test.cpp
Application.mk
# Application.mk
APP_ABI := all
Android.mk
# Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := test-boost
LOCAL_SRC_FILES := test.cpp
include $(BUILD_EXECUTABLE)
test.cpp
// test.cpp
#include <iostream>
int main()
{
return 0;
}
现在来扩展成一个简单的Boost-enabled项目. 这里使用Boost序列化库示例; 其他库类似. 唯一区别是Android.mk中的引用库名称.
(使用 official Boost example ):
gps.hpp
// 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
// 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
# 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)开始支持.