lisz-works

プログラミングと興味を貴方に

C++/CLI Doxygenの呼び出し関係図に出力されない関数を調査した

【スポンサーリンク】

Doxygen

既存のC++/CLIプロジェクトを調査するために、Doxygenで呼び出し関係図を出力させました。

しかしソースとにらめっこしてみると、何故か出力されない関数があることが明らかになりました……

ということで、原因を調査してみました。

結論

C++の場合、クラス定義内だとヘッダファイルにも、定義でなくロジックが書けてしまいます。

どうやらコレが問題でした。

普通はやらないと思いますが、改めて……

ヘッダにロジックを書くのはやめよう!

調査用プロジェクトの作成

調査用に新規プロジェクトを作成しました。

Visual C++ > CLR > Windows フォームアプリケーション

ソースコード

調べるのに使用したソースコードです。

Form1_Load()を起点に、色んな所の関数をアクセスしている感じです。

Form1.h

追加したコード近辺以外の自動生成コードは省略しています。

適当にテキストボックス(text)を作成し、文字列を追加していく処理を作成しました。

#pragma once
#include "stdafx.h"
#include "sub.h"
#include "hoge.h"
#include <stdio.h>
#include <iostream>
#include <msclr/marshal_cppstd.h>

using namespace std;

namespace TestDoxygen {
    (中略)

        String^ sS(string s) {
            return msclr::interop::marshal_as<System::String^>(s);
        }

        void FuncA() { text->Text += "FuncA\r\n"; }
        void FuncB() {
            text->Text += "FuncB\r\n";
            FuncC();
        }

        void FuncC() { text->Text += "FuncC\r\n"; }
        void FuncD() {
            text->Text += "FuncD\r\n";
            string child = FuncX();
            text->Text += sS(child);
        }


        private:
            System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e) {
                FuncA();
                FuncB(); // -> call FuncC
                FuncD();
                FuncY();

                hoge^ h = gcnew hoge();
                text->Text += sS(h->hogeA());
                text->Text += sS(h->hogeD());
            }
    };
}

sub.cpp/h

sub.h

#pragma once

#include "stdafx.h"
#include <iostream>

extern std::string FuncX();
extern std::string FuncY();

sub.cpp

#include "stdafx.h"
#include "sub.h"

std::string FuncX() {
    std::string name = "FuncX\r\n";
    name += "- ";
    name += FuncY();
    return name;
}
std::string FuncY() {
    std::string name = "FuncY\r\n";
    return name;
}

hogeクラス

hoge.cpp

#pragma once
#include <iostream>

using namespace std;

ref class hoge
{
public:
    hoge(void);
    string hogeA() {
        string name = "hogeA\r\n";
        name += hogeB();
        name += hogeC();
        return name;
    }
    string hogeB() {
        string name = "hogeB\r\n";
        name += hogeC();
        return name;
    }
    string hogeC();
    string hogeD();
    string hogeE();
};

hoge.cpp

#include "StdAfx.h"
#include "hoge.h"

hoge::hoge(void){}

string hoge::hogeC() {
    return "hogeC\r\n";
}

string hoge::hogeD() {
    string name = "hogeD\r\n";
    name += hogeE();
    return name;
}

string hoge::hogeE() {
    return "hogeE\r\n";
}

結果

なにかをコールしている関数について挙げていきます。

このような結果になりました。

Form1_Load(Form1.h)

Form1_Load(Form1.h)

FuncB(Form1.h)

呼び出し関係図なし

FuncD(Form1.h)

FuncD(Form1.h)

FuncX(sub.cpp)

FuncX(sub.cpp)

hogeA(hoge.h)

呼び出し関係図なし

hogeB(hoge.h)

呼び出し関係図なし

hogeD(hoge.cpp)

hogeD(hoge.cpp)

謝辞

teratailでご回答くださった方々、ご覧頂いた方々、ありがとうございました。

あとがき

C++/CLI→Doxygenの呼び出し関係図に出力されない関数を調査した結果でした!

なぜForm1.hにゴリゴリ処理を描いてしまったのか……

うらめしい限りです……

とはいえ原因は判明したので、これでやっと対処ができます……

www.lisz-works.com

www.lisz-works.com