簡體   English   中英

WIndows API中的“L”和“LPCWSTR”

[英]The 'L' and 'LPCWSTR' in WIndows API

我發現了

NetUserChangePassword(0, 0, L"ab", L"cd");

將用戶密碼從ab更改為cd。 然而,

NetUserChangePassword(0, 0, (LPCWSTR) "ab", (LPCWSTR) "cd");

不起作用。 返回的值表示密碼無效。

我需要傳遞const char*作為此函數調用的最后兩個參數。 我怎樣才能做到這一點? 例如,

NetUserChangePassword(0, 0, (LPCWSTR) vs[0].c_str(), (LPCWSTR) vs[1].c_str());

其中vsstd::vector<std::string>

你有兩個問題。

首先是實際問題 - 如何做到這一點。 你混淆寬窄的弦樂,從一個到另一個。 帶有L前綴的字符串是一個寬字符串,其中每個字符都是兩個字節( wchar_t )。 沒有L的字符串是單個字節( char )。 你不能使用C風格的轉換 (LPCWSTR) "ab" 從一個轉換為另一個,因為你有一個char數組,並將它轉換為指向寬字符的指針。 它只是更改指針類型,而不是基礎數據。

要從窄字符串轉換為寬字符串,通常使用MultiByteToWideChar 你沒有提到你的窄字符串所在的代碼頁; 你可能會傳入CP_ACP作為第一個參數。 但是,由於您在字符串和wstring之間進行轉換,因此您可能對其他轉換方法感興趣( )。 這將為您提供帶有字符的wstring ,而不是string ,並且wstring.c_str()方法返回指向wchar_t的指針。

第二個是以下誤解:

我需要傳遞const char *作為此函數調用的最后兩個參數。 我怎樣才能做到這一點?

不,你沒有。 你需要傳遞一個寬字符串,你在上面。 你的方法(轉換指針)表明你可能不知道不同的字符串類型和字符編碼,這是每個軟件開發人員都應該知道的。 因此,假設您有興趣,希望您能找到以下參考資料:

我建議您調查使用UNICODE重新編譯應用程序並使用寬字符串。 許多API都是在窄版本和寬版本中定義的,通常這意味着您默認訪問窄版本(您可以通過直接調用A或W版本來訪問這些API的ANSI(窄版)或寬版本 - 它們具有A或W附加到它們的名稱,例如CreateWindowW - 請參見該頁面底部的兩個名稱。您通常不需要擔心這一點。)據我所知,此API始終可用。無論UNICODE如何,它只是它的原型。

那是兩個完全不同的L '。 第一部分是C ++語言語法的一部分。 L前綴一個字符串文字,它變成一個字符串文字; 而不是char數組,你得到一個wchar_t數組。

但是, LPCWSTR中的L不描述字符的寬度。 相反,它描述了指針的大小。 或者,至少,它曾經用過 類型名稱上的L縮寫是16位Windows的遺留物,當有兩種指針時。 指針,其中地址位於當前64 KB段內的某個位置,並且存在指針,它們可能指向當前段之外。 操作系統要求調用者將后者提供給其API,因此所有指針類型名稱都使用LP 如今,只有一種指針; Microsoft保留相同的類型名稱,以便舊代碼繼續編譯。

指定寬字符的LPCWSTR部分是W 但僅僅型鑄造一個char字符串文本LPCWSTR不足以這些字符轉換成寬字符。 相反,會發生什么是類型轉換告訴編譯器你寫的東西一個指向寬字符串的指針,即使它確實不是。 編譯器信任你。 除非你真的比編譯器更了解真實類型,否則不要進行類型轉換。

如果你真的需要傳遞一個const char* ,那么你不需要輸入任何東西,並且你不需要任何L前綴。 一個普通的舊字符串文字就足夠了。 (如果你真的想要轉換為Windows類型,請使用LPCSTR - 沒有W )但是看起來你真正需要傳遞的是const wchar_t* 如上所述,您可以在字符串文字上使用L前綴。

在實際程序中,您可能沒有字符串文字。 用戶將提供密碼,或者您將從其他外部源讀取密碼。 理想情況下,您可以將該密碼存儲在std::wstring ,這類似於std::string但是對於wchar_t而不是char 該類型的c_str()方法返回const wchar_t* 如果你沒有wstringwchar_t的普通數組可能就足夠了。

但是如果你將密碼存儲在std::string ,那么你需要以其他方式將其轉換為寬字符。 要進行轉換,您需要知道std::string字符使用的代碼頁 “當前的ANSI代碼頁”通常是一個安全的賭注; 它由常量CP_ACP表示。 您將在調用MultiByteToWideString時將其用於將操作系統從密碼的代碼頁轉換為Unicode。

int required_size = MultiByteToWideChar(CP_ACP, 0, vs[0].c_str(), vs[0].size(), NULL, 0);
if (required_size == 0)
  ERROR;
// We'll be storing the Unicode password in this vector. Reserve at
// least enough space for all the characters plus a null character
// at the end.
std::vector<wchar_t> wv(required_size);
int result = MultiByteToWideChar(CP_ACP, 0, vs[0].c_str(), vs[0].size(), &wv[0], required_size);
if (result != required_size - 1)
  ERROR;

現在,當你需要一個wchar_t* ,只需使用指向該向量的第一個元素的指針: &wv[0] 如果你需要在wstring ,你可以通過幾種方式從向量構造它:

// The vector is null-terminated, so use "const wchar_t*" constructor
std::wstring ws1 = &wv[0];
// Use iterator constructor. The vector is null-terminated, so omit
// the final character from the iterator range.
std::wstring ws2(wv.begin(), wv.end() - 1);
// Use pointer/length constructor.
std::wstring ws3(&wv[0], wv.size() - 1);

你在這里使用的C風格演員是一種非常生硬的樂器。 他們假設你確切地知道你在做什么。

您需要將ASCII或多字節字符串轉換為API的Unicode字符串。 可能有一個NetUserChangePasswordA函數接受您嘗試傳遞的char *類型,首先嘗試。

LPWSTR定義為wchar_t *(whcar_T是2字節char類型),其解釋方式與正常的1字節字符不同。

LPCWSTR意味着您需要傳遞wchar_t *。

如果你更改vs到std::vector<std::wstring> ,當你傳遞vs [0] .c_str()時會給你一個寬字符

如果你看看http://msdn.microsoft.com/en-us/library/aa370650(v=vs.85).aspx上的例子,你可以看到他們定義了UNICODE,這就是他們使用wchar_t的原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM