Thursday, September 5, 2024

Compile and execute a Simple example of working with Protobuf in C++

You can learn a lot by doing.

Ditto with CMake project building and running in Ubuntu. 

An example cpp-protobuf-example in the github site https://github.com/afiskon/cpp-protobuf-example

comes up often in the google search and I tried compiling it in windows and it gave error.

-- Detecting CXX compile features

-- Detecting CXX compile features - done

-- Could NOT find Protobuf (missing: Protobuf_INCLUDE_DIR)

Its difficult to install protobuf in windows but I did it in Ubuntu(which is just an app in windows now with technology of windows subsystem for linux-WSL).

First I did a git clone with this cmd: 

git clone https://github.com/afiskon/cpp-protobuf-example.git

then I changed directory to  

cd cpp-protobuf-example/

After that I created a build directory by 

mkdir build 

followed by 

cd build 

followed by

cmake .. 

which gave the same error as in windows. In ubuntu its much easier to install required libraries.

sudo apt-get install protobuf-compiler libprotobuf-dev

this command installed everything for me and I was good to go build the app.

cmake ..

worked like charm with following output:

-- Found Protobuf: /usr/lib/x86_64-linux-gnu/libprotobuf.so (found version "3.12.4")

-- Configuring done

-- Generating done

-- Build files have been written to: /home/kamathbol/GitHub/cpp-protobuf-example/build

then the command

cmake --build .

[ 20%] Running cpp protocol buffer compiler on src/proto/Game.proto

[ 40%] Building CXX object CMakeFiles/proto.dir/Game.pb.cc.o

[ 60%] Linking CXX static library libproto.a

[ 60%] Built target proto

[ 80%] Building CXX object CMakeFiles/main.dir/src/Main.cpp.o

[100%] Linking CXX executable main

[100%] Built target main

then upon running the main

./main

Saving heroes...

Loading heroes...


Name: eax

HP: 50

XP: 256

Class: warrior

Weapon: sword

Arrows: 15


Name: afiskon

HP: 25

XP: 1024

Class: mage

Spellbook: fireball, thunderbolt,

Mana: 100

BTW here is the Main.cpp source that gets you this Output:

#include <iostream>
#include <fstream>
#include <stdexcept>
#include <Game.pb.h>

using namespace std;
using namespace me::eax::examples::game;

void saveHero(const char* fname, const Hero& hero) {
    fstream out(fname, ios::out | ios::trunc | ios::binary);
    if(!hero.SerializeToOstream(&out))
        throw runtime_error("saveHero() failed");
}

void loadHero(const char* fname, Hero& hero) {        
    fstream in(fname, ios::in | ios::binary);
    if(!hero.ParseFromIstream(&in))
        throw runtime_error("loadHero() failed");
}

void printHero(const Hero& hero) {
    cout << "Name: " << hero.name() << endl;
    cout << "HP: " << hero.hp() << endl;
    cout << "XP: " << hero.xp() << endl;

    if(hero.has_mage_info()) {
        cout << "Class: mage" << endl;
        cout << "Spellbook: ";
        for(int i = 0; i < hero.mage_info().spellbook_size(); i++) {
            switch(hero.mage_info().spellbook(i)) {
                case Spell::FIREBALL:
                    cout << "fireball, ";
                    break;
                case Spell::THUNDERBOLT:
                    cout << "thunderbolt, ";
                    break;
                default:
                    cout << "(unknown spell), ";
                    break;
            }
        }
        cout << endl;
        cout << "Mana: " << hero.mage_info().mana() << endl;
    } else if(hero.has_warrior_info()) {
        cout << "Class: warrior" << endl;
        cout << "Weapon: " << (
                hero.warrior_info().weapon() == Weapon::SWORD ? "sword" :
                hero.warrior_info().weapon() == Weapon::BOW ? "bow" :
                "(unknown weapon)"
            ) << endl;
        cout << "Arrows: " << hero.warrior_info().arrows_number() << endl;
    } else {
        cout << "Class: (unknown class)" << endl;
    }

    cout << endl;
}

int main() {
    // Verify that the version of the library that we linked against is
    // compatible with the version of the headers we compiled against.
    GOOGLE_PROTOBUF_VERIFY_VERSION;

    Hero warrior;
    warrior.set_name("eax");
    warrior.set_hp(50);
    warrior.set_xp(256);
    warrior.mutable_warrior_info()->set_weapon(Weapon::SWORD);
    warrior.mutable_warrior_info()->set_arrows_number(15);

    Hero mage;
    mage.set_name("afiskon");
    mage.set_hp(25);
    mage.set_xp(1024);
    mage.mutable_mage_info()->add_spellbook(Spell::FIREBALL);
    mage.mutable_mage_info()->add_spellbook(Spell::THUNDERBOLT);
    mage.mutable_mage_info()->set_mana(100);

    cout << "Saving heroes..." << endl;
    saveHero("eax.dat", warrior);
    saveHero("afiskon.dat", mage);

    cout << "Loading heroes..." << endl;
    Hero warrior2;
    Hero mage2;
    loadHero("eax.dat", warrior2);
    loadHero("afiskon.dat", mage2);

    cout << endl;
    printHero(warrior2);
    printHero(mage2);
}


No comments:

Post a Comment