提问人:ddevienne 提问时间:8/10/2023 最后编辑:ddevienne 更新时间:8/10/2023 访问量:36
当 TCHAR 可以映射到 char 或 wchar_t 时,将 TCHAR 字符串打印到 std::ostream
Print TCHAR string to std::ostream when TCHAR can map to either char or wchar_t
问:
我在不同的可执行文件中重用相同的完全相同的源文件(用于命令行解析)。我不使用库,而是直接在每个 exe 中构建相同的源代码。
最近,我添加了一个选项来列出可执行文件使用的所有共享库。这在我测试的 exe 中工作正常,但是当我在不同的 exe 上尝试时,它编译但工作不正常,打印地址而不是共享库的路径。我(隐约)知道 TCHAR。不知何故,这两个具有不同依赖项(通过 CMake 构建引入)的 ex 最终具有不同的 TCHAR 类型 ( vs )。两个前任都接受了,但第一个是打电话,第二个是打电话,因此打印地址。char
wchat_t
os << me32.szExePath
op<<(..., const char*)
op<<(..., const void*)
好的,我想,我将只使用编译时 if (即 ) 因为我在 C++ 17 中,并在案例中使用原样,并明确地将其从 转换为 else。下面的代码修复了第二个 exe,因此它打印了路径(而不是地址)。但后来它打破了第一个前任!!if constexpr
me32.szExePath
char
wchar_t
char
1>...\CliContext.cpp(1703,81): error C2664: 'errno_t wcstombs_s(size_t *,char *,size_t,const wchar_t *,size_t)': cannot convert argument 4 from 'char [260]' to 'const wchar_t *'
1>...\CliContext.cpp(1703,55): message : Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt\stdlib.h(999,26): message : see declaration of 'wcstombs_s'
这对我来说毫无意义,因为第一个 exe 不应该编译两个分支。毕竟,它不能有两个相同的值,不是吗?if constexpr
sizeof(*me32.szExePath)
我显然错过了什么......有人可以帮忙吗?
有没有办法编写此代码,使其在两种 TCHAR 情况下都有效,用于打印到 ?std::ostream
PS:我之前尝试过另一个编译时if,同样失败了。if constexpr (std::is_same_v<wchar_t, *me32.szExePath>)
PPS:这些是跨平台的 exe。我没有展示 linux 方面。我确实想使用而不是其他东西来打印。std::ostream
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
static void sharedLibraries(std::ostream& os) {
auto dwPID = GetCurrentProcessId();
HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
if (hModuleSnap == INVALID_HANDLE_VALUE) {
raise("CreateToolhelp32Snapshot (of modules)");
}
using Handle_uptr = std::unique_ptr<void, decltype(&CloseHandle)>;
Handle_uptr h(hModuleSnap, &CloseHandle);
MODULEENTRY32 me32;
me32.dwSize = sizeof(me32);
if (!Module32First(hModuleSnap, &me32)) {
raise("Module32First");
}
do {
assert(me32.th32ProcessID == dwPID);
if constexpr (sizeof(*me32.szExePath) == 1) {
os << me32.szExePath << std::endl;
}
if constexpr (sizeof(*me32.szExePath) == 2) {
size_t size = 0; char path[260*4];
wcstombs_s(&size, path, sizeof(path), me32.szExePath, sizeof(path)-1);
os << path << std::endl;
}
} while (Module32Next(hModuleSnap, &me32));
}
答:
使用它对我有用:
#ifdef UNICODE
size_t size = 0; char path[260*4];
wcstombs_s(&size, path, sizeof(path), me32.szExePath, sizeof(path)-1);
os << path << std::endl;
#else
os << me32.szExePath << std::endl;
#endif
不过,我仍然想知道为什么会失败。FWIW。if constexpr
评论
path
={}
raise("...");
- 这是 Windows 特定的重载吗? 需要一个参数。 Tries 将类型与值进行比较。这永远行不通。std::raise
int
std::is_same_v<wchar_t, *me32.szExePath>
std::wostream
std::is_same_v<TCHAR, wchar_t>
wcstombs_c
decltype