1. 程式人生 > >C++ Yaml檔案解析安裝及使用 yaml-cpp

C++ Yaml檔案解析安裝及使用 yaml-cpp

安裝 yaml-cpp

克隆官方庫

git clone https://github.com/jbeder/yaml-cpp.git

編譯 yaml-cpp

cd yaml-cpp # 進入克隆的資料夾
mkdir build
cd build
cmake ..
make
make install

沒出現報錯的話就完成了編譯

示例程式碼

robot.cpp

#include "yaml-cpp/yaml.h" //安裝yaml-cpp參考google code 主頁
#include <iostream>
#include <fstream>
#include <string>
#include <vector> // our data types //這個例子好像是取自開源遊戲引擎ogre,隨便說的 struct Vec3 { //位置座標 float x, y, z; }; struct Power { //招式,魔法 std::string name; //招式名字,如 葵花寶典 int damage; //傷害值 }; struct Monster { //怪獸 std::string name; Vec3 position; std::vector <Power> powers; }; // now the extraction operators for these types //過載 >> 預算符。。。。
void operator >> (const YAML::Node& node, Vec3& v) { node[0] >> v.x; node[1] >> v.y; node[2] >> v.z; } void operator >> (const YAML::Node& node, Power& power) { node["name"] >> power.name; node["damage"] >> power.damage; } void
operator >> (const YAML::Node& node, Monster& monster) { node["name"] >> monster.name; node["position"] >> monster.position; const YAML::Node& powers = node["powers"]; for(unsigned i=0;i<powers.size();i++) { Power power; powers[i] >> power; monster.powers.push_back(power); } } int main() //測試程式 { std::ifstream fin("robot.yaml"); // 讀入yaml配置檔案。 YAML::Parser parser(fin); //yaml 分析輸入的配檔案。出錯丟擲YAML::ParserException YAML::Node doc; parser.GetNextDocument(doc); //doc 就是我們的yaml配置檔案 for(unsigned i=0;i<doc.size();i++) {//i的實際值是0,1,2 ;關聯yaml 中三個大的struct:ogre,dragon,wizard Monster monster; doc[i] >> monster; std::cout << monster.name << "\n"; } return 0; }

robot.yaml

- name: Ogre
  position: [0, 5, 0]
  powers:
    - name: Club
      damage: 10
    - name: Fist
      damage: 8
- name: Dragon
  position: [1, 0, 10]
  powers:
    - name: Fire Breath
      damage: 25
    - name: Claws
      damage: 15
- name: Wizard
  position: [5, -3, 0]
  powers:
    - name: Acid Rain
      damage: 50
    - name: Staff
      damage: 3

編譯 robot.cpp

需要制定連結庫

g++ robot.cpp /usr/local/lib/libyaml-cpp.a

如果找不到的話可以使用 find 命令查詢相關檔案

find / -name yaml-cpp.a

如果不這樣可能會報錯:

/tmp/ccYcxLtu.o: In function `main':
robot.cpp:(.text+0x24b): undefined reference to `YAML::Parser::Parser(std::istream&)'
robot.cpp:(.text+0x25a): undefined reference to `YAML::Node::Node()'
robot.cpp:(.text+0x273): undefined reference to `YAML::Parser::GetNextDocument(YAML::Node&)'
robot.cpp:(.text+0x30f): undefined reference to `YAML::Node::size() const'
robot.cpp:(.text+0x331): undefined reference to `YAML::Node::~Node()'
robot.cpp:(.text+0x340): undefined reference to `YAML::Parser::~Parser()'
robot.cpp:(.text+0x388): undefined reference to `YAML::Node::~Node()'
robot.cpp:(.text+0x39c): undefined reference to `YAML::Parser::~Parser()'
/tmp/ccYcxLtu.o: In function `YAML::Node const* YAML::Node::FindValueForKey<std::string>(std::string const&) const':

就是一堆找不到庫檔案

執行結果

Ogre
Dragon
Wizard

難點分析與總結

總結一下知識忙點和誤區

什麼是 .a 與 .so 檔案

靜態連結庫(.a) 與動態連結庫(.so)

在這裡插入圖片描述

  • 庫有兩種,一種是 靜態連結庫,一種是 動態連結庫,不管是哪一種庫,要使用它們,都要在程式中包含相應的 include 標頭檔案

靜態連結庫

  • 靜態連結庫 即在連結階段,將原始檔中用到的庫函式與彙編生成的目標檔案.o合併生成可執行檔案。該可執行檔案可能會比較大。這種連結方式的好處是:方便程式移植,因為可執行程式與庫函式再無關係,放在如何環境當中都可以執行。 缺點是:檔案太大
  • 靜態連結的使用, 需要找到檔案的位置和庫檔名
      g++ -o test test.cpp -L./addlib -ladd
    
    -L是指定載入庫檔案的路徑
    
    -l是指定載入的庫檔案。
    

動態連結庫

在這裡插入圖片描述

在這裡插入圖片描述

g++(gcc)編譯選項

  • -shared :指定生成動態連結庫。
  • -static :指定生成靜態連結庫。
  • -fPIC :表示編譯為位置獨立的程式碼,用於編譯共享庫。目標檔案需要建立成位置無關碼,念上就是在可執行程式裝載它們的時候,它們可以放在可執行程式的記憶體裡的任何地方。
  • -L. :表示要連線的庫所在的目錄。
  • -l:指定連結時需要的動態庫。編譯器查詢動態連線庫時有隱含的命名規則,即在給出的名字前面加上lib,後面加上.a/.so來確定庫的名稱。
  • -Wall :生成所有警告資訊。
  • -ggdb :此選項將盡可能的生成gdb的可以使用的除錯資訊。
  • -g :編譯器在編譯的時候產生除錯資訊。
  • -c :只啟用預處理、編譯和彙編,也就是把程式做成目標檔案(.o檔案)。
  • -Wl,options :把引數(options)傳遞給連結器ld。如果options中間有逗號,就將options分成多個選項,然後傳遞給連結程式。

參考文章