LoginSignup
4
5

More than 5 years have passed since last update.

C#, VB, C++/CLI, MFCから呼ぶLoggerModuleを作るメモ

Posted at

この記事は?

『C#』『VB』『C++/CLI』『MFC』を使ったプロジェクトで、共通のLoggerを作成する上でのモジュール間呼び出しに関するtipsをまとめたメモ。
やり取りに関係しないところは適当に簡略化してます。

<必要な要素>

  • IFは共通であること
  • ファイル名、関数名、行数を勝手に表示すること

誰向け?

  • C#やVBで出来たソリューションにMFCの古い秘伝のソースを入れる必要が出た悲しき定めの人
  • ログ出力初心者さん?

全体観

ほげ.png

LogModule

『C++/CLI』で作成。
C#, VBからもC++/CLI、MFCからも呼ぶ必要があるためです。
今回の話に全く関係ありませんが、NLog使いました。

Logger.cpp
void CLogger::WriteInfoMessage(String^ message, String^ file, String^ func, int line)
{
    CLogger::Initialize();
    CLogger::logger->WriteLog(Loglv::Info, message, file, func, line);
}

<簡単な説明>
秘伝のソース過ぎて最初にどこを通るか全くわからないので、全ての外部IFにインスタンス作成等のInitializeがついてます。
WriteLog内でメッセージをフォーマットして、Nlogのインスタンスに対しInfoメソッドを呼んでいます。

C#, VB用IF

『C#』で作成。
LogModuleのdllをLib参照しているプロジェクト。

LoggerIF.cs
public static void WriteInfoMessage(
    string message,
    [CallerFilePath]string file = "",
    [CallerMemberName]string func = "",
    [CallerLineNumber]int line = 0)
{
    Logger.WriteInfoMessage(message, file, func, line);
}

<簡単な説明>

属性名 効果
CallerFilePath 呼び出し元ファイル名を取得
CallerMemberPath 呼び出し元関数名を取得
CallerLineNumber 呼び出し元行数を取得

LogModuleのWriteInfoMessage等ログ出力関数を直接を呼び出しています.

C++/CLI, MFC用ヘッダファイル

LogModule, C++/CLIプロジェクト、MFCプロジェクト共用。

LoggerIF.h
#ifdef LOGDLL_EXPORTS
#define LOGDLL_API __declspec(dllexport) 
#else
#define LOGDLL_API __declspec(dllimport) 
#endif

#define WriteInfoMessage(message) _WriteInfoMessage(message, __FILE__, __FUNCTION__, __LINE__)

extern "C" {
    LOGDLL_API void _WriteInfoMessage(const char* message, const char* file, const char* func, int line);
}

<簡単な説明>

定義名 効果
__FILE__ 呼び出し元ファイル名を取得
__FUNCTION__ 呼び出し元関数名を取得
__LINE__ 呼び出し元行数を取得

WriteInfoMessageをDefineで定義し、ファイル名等を追加で取得してextern"C"の内部関数に渡しています。
また、LogModule内のログ出力クラスにてヘッダInclude時にLOGDLL_EXPORTSを定義することで、呼び出し元/呼び出し先のdllimport/dllexportを分けています。(お決まり)

Logger.cpp
#include "Logger.h"
#define LOGDLL_EXPORTS

呼び出し部分

C#

sample.cs
using static Logs.LoggerIF;
...
    WriteInfoMessage("test");

VB

sample.vb
Imports Logs.LoggerIF;
...
    WriteInfoMessage("test")

C++/CLI, MFC

sample.cpp

#include "LoggerIF.h"
...
    WriteInfoMessage("test");

妥協点

LogModuleのあるC++/CLIにもCallerFilePath等は存在しているため、C#, VB用IFを使わずC#側から直接LogModuleを呼び出すことはもちろん可能です。
ただし、VB側から呼び出してもファイル名などが入ってきませんでした。

おそらく中間コードからVBに直す際、VBの仕様に合わせるために初期値が設定されていないと強制的に後からNothingを入れてしまうから・・・?CallerMemberPath等は値が設定されている場合無視されてしまうので、結果ファイル名が入って来ないのではないかと。

OptionalAttributeやDefaultValue等試してみてもうまく出来ず断念。そのため、C#でIFを作成しています。
対処法がわかればこのIFは不要です。

C#側からは初期値問題が発生しないので直接LogModuleを呼び出しても問題ありませんが、どうせC#でIFを作るなら参照しない理由がないので、C#側からもこのIFを参照しています。

4
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5