Godot 4 ソースコード解析 - ログ出力

ソフトウェアを使用すると、ログからさらに多くの走行情報を得ることができ、ログを調べることも一種の学習になります。

Godot には、コンソールありとコンソールなしの 2 つの動作モードがあります。コンソールの場合、実行時に DOS ウィンドウが開き、特定のログ情報が DOS ウィンドウに表示されます。しかし、私の知る限り、コンソールがなければ、これらのログはどこに表示すればよいのかわかりません。

DrGraph プレフィックス出力

シングルステップ デバッグに基づいて、さまざまなログ出力が CompositeLogger の各ロガーの logv 関数と log_error 関数を呼び出すことがわかります。また、Windows で実行すると、Windows TerminalLogger インスタンス オブジェクトが存在し、最終的に Windows TerminalLogger::logv を呼び出します。 /log_error 関数。それが機能するかどうかを確認するために、Windows TerminalLogger::logv の出力に DrGraph プレフィックスを追加しました。


void WindowsTerminalLogger::logv(const char *p_format, va_list p_list, bool p_err) {
	if (!should_log(p_err)) {
		return;
	}

	const unsigned int BUFFER_SIZE = 16384;
	char buf[BUFFER_SIZE + 1]; // +1 for the terminating character
	int len = vsnprintf(buf, BUFFER_SIZE, p_format, p_list);
	if (len <= 0) {
		return;
	}
	if ((unsigned int)len >= BUFFER_SIZE) {
		len = BUFFER_SIZE; // Output is too big, will be truncated
	}
	buf[len] = 0;

	int wlen = MultiByteToWideChar(CP_UTF8, 0, buf, len, nullptr, 0);
	if (wlen < 0) {
		return;
	}

	wchar_t *wbuf = (wchar_t *)memalloc((len + 1) * sizeof(wchar_t));
	ERR_FAIL_NULL_MSG(wbuf, "Out of memory.");
	MultiByteToWideChar(CP_UTF8, 0, buf, len, wbuf, wlen);
	wbuf[wlen] = 0;

	if (p_err) {
		fwprintf(stderr, L"DrGraph - %ls", wbuf);
	} else {
		wprintf(L"DrGraph - %ls", wbuf);
	}

	memfree(wbuf);

#ifdef DEBUG_ENABLED
	fflush(stdout);
#endif
}

log_error は最終的に logv を呼び出すようですので、残りを変更する必要はありません。コンパイル後、コンソールモードで実行すると、次のように変わりました。

 ログファイル出力

非コンソール モードの起動および操作の場合、ログ出力関数には出力を表示する場所がありません。

	if (p_err) {
		fwprintf(stderr, L"DrGraph - %ls", wbuf);
	} else {
		wprintf(L"DrGraph - %ls", wbuf);
	}

この情報を記録するためにログ出力ファイルを追加できます。ofstream を通じていくつかの関数を実装するだけです。

std::string logFileName = "";
std::string getLogFileName() {
	if (logFileName.length() == 0) {
		TCHAR szFileName[256];
		memset(szFileName, 0, sizeof(szFileName));
		GetModuleFileName(NULL, szFileName, sizeof(szFileName));
		logFileName = szFileName;
		int nPos = logFileName.rfind("\\");
		if (nPos != -1)
			logFileName.erase(nPos, logFileName.size() - nPos);
		logFileName += "\\DrGraph_debug.log";
	}
	return logFileName;
}

std::ofstream * getLogStream() {
	std::ios_base::openmode mode = logFileName.length() > 0 ? std::ios_base::app : std::ios_base::trunc;
	std::string fileName = getLogFileName();
	std::ofstream * os = new std::ofstream(fileName, mode);
	if (!os->is_open())
		fwprintf(stderr, L"DrGraph - Can't open log file %hs to write", fileName.c_str());	// %Ts
	return os;
}

std::string dateTimePrefix() {
	struct tm *ptr;
	time_t lt;
	char str[80];
	lt = time(NULL);
	ptr = localtime(&lt);
	strftime(str, 100, "%F %T", ptr);
	auto now = std::chrono::system_clock::now();
	std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
	std::ostringstream oss;
	oss.fill('0');
	oss << str << ":" << std::setw(3) << ms.count() << " > Log by DrGraph > ";
	return oss.str();
}

logv 呼び出しの後にカスタム ログ出力を追加する

	std::ofstream *os = getLogStream();
	(*os) << dateTimePrefix() << buf;	
	delete os;

このようにして、実行後、ログ ファイル DrGraph_debug.log が自動的に生成されます。

プラスマクロ定義

#define DEBUG_SOURCE_POS print_line("[SourceCode Position Info] > Function", __FUNCTION__, "@File", __FILE__, "::Line", __LINE__)

ログを出力したい場所にDEBUG_SOURCE_POSを追加すると簡易ソースコード情報が確認できます

気分がずっと良くなります。 

おすすめ

転載: blog.csdn.net/drgraph/article/details/131061646