概要
行いたいこと : Android用のappでxml形式のファイル(colladaファイル)を読み込みたい
環境 : NDK(C++)
方法 : boostライブラリに含まれるproperty_tree(ptree)ライブラリを用いてxmlファイルをパースする
boostライブラリとは
wikipediaより
Boost (ブースト)とは、C++の先駆的な開発者のコミュニティ、およびそのコミュニティによって公開されているオープンソースのソフトウェアライブラリのことを指す。
https://ja.wikipedia.org/wiki/Boost_C%2B%2B%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA
ライセンスはBoost Software Licenseであり、抜粋すると
- 本ライセンスの対象となる本ソフトウェアのコピーおよび付属文書を入手した個人または組織に対して、本ソフトウェアの使用、複製、公開、頒布、実行、伝送、および二次的著作物の作成を無償で許可します。
- 本ソフトウェアのコピーの一部または全部、あるいは本ソフトウェアのすべての二次的著作物に添付されなければなりません。
となっている。
日本語訳参考サイト : https://licenses.opensource.jp/BSL-1.0/BSL-1.0.html
ptreeの導入方法
ここではptreeだけを使用したいという要求なので、使用したい分だけ該当ファイルでincludeするようにする。
boostホームページのDOWNLOADから最新版をダウンロード後、boostのディレクトリとライセンス関係のファイルだけをプロジェクトに追加する。
ptreeについてはヘッダーファイルの中に定義まで書かれているので、CMakeListのinclude_directoriesにboostファイルのパスを追加するだけでよい。
set(BOOST_DIR ${SRC_DIR}/boost) //boost ライブラリのパス
include_directories( /*他のパス*/ ${BOOST_DIR})
※モジュールにboostライブラリを使用する場合であっても、appのCMakeListにも同様のパスの追加が必要。
あとはboostライブラリを呼び出す箇所でincludeする。
#include "boost/property_tree/ptree.hpp"
#include "boost/property_tree/xml_parser.hpp"
#include "boost/foreach.hpp"
#include "boost/lexical_cast.hpp"
Androidでの注意点
ファイル読み込みの部分にて、windows/Linuxであればファイルストリーム(std::ifstream)を使用できるが、Androidではファイルストリームを使用できない。
xml_parser.hppを見ると
void read_xml(std::basic_istream<
typename Ptree::key_type::value_type
> &stream,
Ptree &pt,
int flags = 0)
{
read_xml_internal(stream, pt, flags, std::string());
}
void read_xml(const std::string &filename,
Ptree &pt,
int flags = 0,
const std::locale &loc = std::locale())
{
BOOST_ASSERT(validate_flags(flags));
std::basic_ifstream<typename Ptree::key_type::value_type>
stream(filename.c_str());
if (!stream)
BOOST_PROPERTY_TREE_THROW(xml_parser_error(
"cannot open file", filename, 0));
stream.imbue(loc);
read_xml_internal(stream, pt, flags, filename);
}
とあって、ファイル名を指定せずにisteamから読み込めるバージョン(1つめのread_xml関数)がありがたくも用意されているので、こちらを使用する。
AAsetManagerの関数でファイルをchar配列に読み込み、それを一旦stringbufに書き込む。
その後、stringbufを引数にistreamを作成し、先ほどのremd_xmlに渡す。
using namespace boost::property_tree;
ptree tree;
AAsset* file = AAssetManager_open(app->activity->assetManager,
filePath, AASSET_MODE_BUFFER);
size_t fileLength = AAsset_getLength(file);
char* fileContent = new char[fileLength];
AAsset_read(file, fileContent, fileLength);
std::stringbuf strbuf(fileContent);
std::basic_istream stream(&strbuf);
read_xml(stream, tree);
最後に
はてなブログにも色々書いているので、興味のある方はご覧ください。
https://blog.hatena.ne.jp/Aqoole_Hateena/aqoole-hateena.hatenablog.com/
ソースコードはGitHubに上げております。
https://github.com/kodai731/Aqoole-Engine-Android-Vulkan-Rendering-Engine-