ラベル C++ の投稿を表示しています。 すべての投稿を表示
ラベル C++ の投稿を表示しています。 すべての投稿を表示

2019/09/01

Doxygen対応のコメント記載方法(C, C++)

背景


仕事でプログラミングする際に、関数に説明を追加する場合が多いため、Doxygen対応のコメント方法について記載する。

記事の目的


Doxygen対応のコメント記載方法について記す

Doxygen対応のコメント


ここでは、Doxygen対応のコメント記載方法について記す。

ファイルへのコメント

ファイルの先頭に、ファイル内のプログラムの説明を記載する。
/**
 * @file ファイル名.h
 * @brief 簡単な説明
 * @author 書いた人
 * @date 作成日付
 */

関数へのコメント

関数毎に、関数の説明を記載する。
/**
 * @fn func1(int, int)
 * ここに関数の説明を書く
 * @brief 要約説明
 * @param arg1 引数の説明
 * @param arg2 引数の説明
 * @return 戻り値の説明
 * @sa 参照すべき関数を書けばリンクが貼れる
 * @detail 詳細な説明
 */
void func1(int arg1, int arg2)
{}

変数へのコメント

変数毎に、変数の説明を記載する。
//! 変数へのコメント
int a = 0;

マクロへのコメント

マクロ毎に、マクロの説明を記載する。
/** @def
 * マクロのコメント
 */
#define MAX_XXX 256

列挙体へのコメント

列挙体毎に、列挙体の説明を記載する。
/**
 * @enum Enum
 * 列挙体の説明
 */
enum Enum {
    //! 列挙体の各要素の説明
    EnumItem1 = 0x00,

    //! 列挙体の各要素の説明
    EnumItem2 = 0x01
};

構造体へのコメント

構造体体毎に、構造体の説明を記載する。
/**
 * @struct     構造体名
 * @brief      構造体の説明
**/
struct Struct{
    //! 構造体の各要素の説明
    StructItem1 = 0x00,

    //! 構造体の各要素の説明
    StructItem2 = 0x01
};

クラスへのコメント

クラス毎に、クラスの説明を記載する。
int global_var1
int global_var2
int global_var3
int global_var4

/*! @class Class1
    @brief  クラスの説明
*/
class Class1 {
public:
    /*! メンバ1の説明 */
    int member1;

    int member2; /*!< メンバ2の説明を横につける */

    /*! メソッド1の説明 */
    int method1(int var1, int var2);

    /*! メソッド2の説明。詳細説明
        @param[out]     var1    var1の説明
        @param[in]      var2    var2の説明
        @param[in,out]  var3    var3の説明
        @par            Refer
        - 参照するグローバル変数 global_var1
        - 参照するグローバル変数 global_var2
        @par            Modify
        - 変更するグローバル変数 global_var3
        - 変更するグローバル変数 global_var4
        @return         成功 0, 失敗 0 以外 など
        @exception      例外。不要であればnoneを記述
    */
    int method2(int var1, int var2, int var3) {
    ...
    }
};

まとめ


  • Doxygen対応のコメント記載方法を調査、記載した

参考文献



変更履歴


  1. 2019/09/01: 新規作成

2019/08/28

C++でリングバッファを実装

背景


仕事でプログラミングする際に、リングバッファを多用するため、テンプレートを作成する

記事の目的


リングバッファのテンプレートを作成する

リングバッファ


ここでは、リングバッファの記述方法について記載する。

仕様

テンプレートの仕様について記載する。
  • 複数のスレッドから、バッファサイズの変更、バッファの書き込み、バッファの読み込みが可能
  • データが格納されていないバッファにアクセスすると、エラーが表示され、デフォルトのデータが返される

テンプレート

リングバッファを使用するテンプレートを記載する。
// ring_buffer.cpp
#include <stdio.h>
#include <mutex>

// リングバッファに格納するデータ形式
struct Data
{
    int number = 0;
};

// 前方宣言
class RingBuffer
{
    public:
        // コンストラクタ(リングバッファのサイズを指定(2の冪乗が最適))
        RingBuffer(uint buffer_size_in);
        // デストラクタ
        ~RingBuffer();
        // リングバッファのサイズを指定(0より大の整数、2の冪乗が最適)
        void setBufferSize(uint buffer_size_in);
        // リングバッファのサイズを取得
        uint getBufferSize();
        // リングバッファにデータを書き込み
        void writeBuffer(Data data_in);
        // リングバッファのデータを読み込み(0: 最新, BufferSize: 最古)
        Data readBuffer(uint read_pointer_in);
    private:
        // コンストラクタ(宣言時に必ずバッファサイズを宣言する)
        RingBuffer();
        // リングバッファのポインタ
        Data *data_;
        // リングバッファのサイズ
        uint buffer_size_   = 0;
        // リングバッファ内に書き込まれたデータ数
        uint data_size_     = 0;
        // 書き込みポインタ(最新データのポインタ)
        uint write_pointer_ = 0;
        // mutex(読み書き、バッファサイズ変更を排他)
        std::mutex mtx_;
};
// コンストラクタ(プライベート関数)
RingBuffer::RingBuffer()
{}
// コンストラクタ(リングバッファのサイズを指定)
RingBuffer::RingBuffer(uint buffer_size_in)
{
    // リングバッファのサイズを指定、メモリ上にバッファを確保
    setBufferSize(buffer_size_in);
}
// デストラクタ(リングバッファを削除)
RingBuffer::~RingBuffer()
{
    if (buffer_size_ > 0)
    {
        delete[] data_;
    }
}
// リングバッファのサイズを指定、メモリ上にバッファを確保
void RingBuffer::setBufferSize(uint buffer_size_in)
{
    if (buffer_size_in > 0)
    {
        // 排他
        std::lock_guard<std::mutex> lock(mtx_);
        // すでにメモリ上にリングバッファが確保されている場合は、一旦削除
        if (buffer_size_ > 0)
        {
            delete data_;
        }
        // リングバッファのサイズを保持
        buffer_size_ = buffer_size_in;
        // 内部変数の初期化
        data_size_   = 0;
        write_pointer_   = 0;
        // メモリ上にリングバッファを確保
        data_ = new Data[buffer_size_in];
    }
    else
    {
        fprintf(stderr, "Error: [RingBuffer] Please set buffer size more than 0.\n");
    }
}
// リングバッファのサイズを取得
uint RingBuffer::getBufferSize()
{
    // 排他
    std::lock_guard<std::mutex> lock(mtx_);
    return buffer_size_;
}
// リングバッファにデータ書き込み
void RingBuffer::writeBuffer(Data data_in)
{
    // リングバッファが確保されている場合のみ処理
    if (buffer_size_ > 0)
    {
        // 排他
        std::lock_guard<std::mutex> lock(mtx_);
        // 書き込みポインタを進める
        write_pointer_ ++;
        write_pointer_ %= buffer_size_;
        // データを書き込み
        data_[write_pointer_] = data_in;
        // 書き込んだデータ数を保持
        if (data_size_ < buffer_size_)
        {
            data_size_ ++;
        }
    }
    else
    {
        fprintf(stderr, "Error: [RingBuffer] Buffer is not allocated.\n");
    }
}

Data RingBuffer::readBuffer(uint read_pointer_in)
{
    // 過去にデータが書き込まれていないデータのポインタにはアクセスさせない
    if (read_pointer_in < data_size_)
    {
        // 排他
        std::lock_guard<std::mutex> lock(mtx_);
        // 現在の最新データのポインタを0, 古いほど値が大きくなる(最大: Buffer Size)
        uint read_pointer = (buffer_size_+write_pointer_-read_pointer_in)%buffer_size_;
        return data_[read_pointer] ;
    }
    else
    {
        fprintf(stderr, "Error: [RingBuffer] Read pointer is out of buffer. (%d / %d)\n",
                            read_pointer_in, data_size_);
        Data data;
        return data;
    }
}

// テストコード
int main()
{
    fprintf(stdout, "Error pattern -------\n"); 
    // 宣言(エラー)
    RingBuffer buf(0);
    Data data_1;
    data_1.number = 0;
    // データ書き込み(エラー)
    buf.writeBuffer(data_1);
    // データ読み込み(エラー)
    buf.readBuffer(1);
    // リングバッファのサイズを再設定
    buf.setBufferSize(10);
    // データ読み込み(エラー)
    buf.readBuffer(1);

    fprintf(stdout, "Normal pattern ------\n"); 
    for (uint i=0; i<2*buf.getBufferSize(); i++)
    {
        Data data_2;
        data_2.number = i;
        // データ書き込み(正常)
        buf.writeBuffer(data_2);
        fprintf(stdout, "%d / %d\n",i, 2*buf.getBufferSize()-1); 
        // 1. データ読み込み(最古のデータ 0 or 10)
        fprintf(stdout, "1. buf.data[%d].number: %d\n", 
            i%buf.getBufferSize(),
            buf.readBuffer(i%buf.getBufferSize()).number);
        // 2. データ読み込み(最新のデータ 0 to 19)
        fprintf(stdout, "2. buf.data[%d].number: %d\n", 
            0,buf.readBuffer(0).number);
    }
    return 0;
}

テンプレートのコンパイル方法

テンプレートのコンパイル方法を記載する。
$ g++ ./ring_buffer.cpp -std=c++11 -o ring_buffer_sample

テンプレートの実行結果

テンプレートの実行結果を記載する。
$ ./ring_buffer_sample
Error pattern -------
Error: [RingBuffer] Please set buffer size more than 0.
Error: [RingBuffer] Buffer is not allocated.
Error: [RingBuffer] Read pointer is out of buffer. (1 / 0)
Error: [RingBuffer] Read pointer is out of buffer. (1 / 0)
Normal pattern ------
0 / 19
1. buf.data[0].number: 0
2. buf.data[0].number: 0
1 / 19
1. buf.data[1].number: 0
2. buf.data[0].number: 1
2 / 19
1. buf.data[2].number: 0
2. buf.data[0].number: 2
3 / 19
1. buf.data[3].number: 0
2. buf.data[0].number: 3
4 / 19
1. buf.data[4].number: 0
2. buf.data[0].number: 4
5 / 19
1. buf.data[5].number: 0
2. buf.data[0].number: 5
6 / 19
1. buf.data[6].number: 0
2. buf.data[0].number: 6
7 / 19
1. buf.data[7].number: 0
2. buf.data[0].number: 7
8 / 19
1. buf.data[8].number: 0
2. buf.data[0].number: 8
9 / 19
1. buf.data[9].number: 0
2. buf.data[0].number: 9
10 / 19
1. buf.data[0].number: 10
2. buf.data[0].number: 10
11 / 19
1. buf.data[1].number: 10
2. buf.data[0].number: 11
12 / 19
1. buf.data[2].number: 10
2. buf.data[0].number: 12
13 / 19
1. buf.data[3].number: 10
2. buf.data[0].number: 13
14 / 19
1. buf.data[4].number: 10
2. buf.data[0].number: 14
15 / 19
1. buf.data[5].number: 10
2. buf.data[0].number: 15
16 / 19
1. buf.data[6].number: 10
2. buf.data[0].number: 16
17 / 19
1. buf.data[7].number: 10
2. buf.data[0].number: 17
18 / 19
1. buf.data[8].number: 10
2. buf.data[0].number: 18
19 / 19
1. buf.data[9].number: 10
2. buf.data[0].number: 19

備考


まとめ


  • C++でリングバッファを記述するテンプレートを記載した

参考文献



変更履歴


  1. 2019/08/28: 新規作成
  2. 2019/08/28: 備考追記
  3. 2019/09/02: 仕様追記

MQTTの導入

背景 IoTデバイスの接続環境構築のため、MQTT(mosquitto)の導入を行った。 記事の目的 MQTT(mosquitto)をUbuntuに導入する mosquitto ここではmosquittoについて記載する。 MQTT MQTT(Message Qu...