传递参数(带有std :: string转换为LPWSTR的Prob)

时间:2014-05-11 10:58:22

标签: c++ winapi

这有点烦人。我尝试将参数从NPAPI插件传递给EXE。

第一条信息:可执行文件目前是占位符,只打印出传递的参数作为消息框:

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {
    /* Print out the arguments */
    MessageBox(NULL, lpCmdLine, TEXT("World of RPG"), NULL);

    /* Exit with return code 0x00 */
    return 0;
}

当我尝试通过Visual Studio启动应用程序时(以参数" -console"启动),将正确提示消息框:

enter image description here enter image description here

然而,我尝试从我的NPAPI插件执行可执行文件:

/* Javascript call: document.getElementById("myPlugin").startGame("-console"); */
std::string WoRPGAPI::startGame(const std::string& method_args) {
    /* Define JSON result variables */
    FB::VariantMap json;
    Json::StyledWriter writer;

    /* Define process variables*/
    PROCESS_INFORMATION processInformation = { 0 };
    STARTUPINFO startupInfo = { 0 };
    startupInfo.cb = sizeof(startupInfo);

    LPWSTR game_exe = LgetGamePath("World of RPG.exe").c_str(); // example: "C:\\Program Files (x86)\\World of RPG\\World of RPG.exe"
    LPWSTR game_args = method_args.c_str(); // example: "-console"

    /* Create the Process */
    BOOL status = CreateProcess(game_exe, game_args, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation);

    /* Check the process status */
    if (!status) {
        DWORD dLastError = GetLastError();
        LPCTSTR strErrorMessage = NULL;

        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, dLastError, 0, (LPWSTR)&strErrorMessage, 0, NULL);

        json["code"] = dLastError;
        json["message"] = strErrorMessage;
    }

    json["status"] = status;

    /* get JSON back to the browser */
    return writer.write(FB::variantToJsonValue(json));
}

结果如下:

enter image description here

好的,尝试使用startGame("This is a longer string!")的较长字符串进行测试。你看,只有第一个单词会被切断。我已经尝试了30多分钟来解决这个问题:

enter image description here

你能告诉我,我做错了什么吗? 我尝试过很多转化示例,将std::string转换为LPWSTR但没有任何效果。其他方法给了我像中文字符的密码输出。

1 个答案:

答案 0 :(得分:2)

  1. MessageBox函数将两个参数正确输入为LPCTSTR。假设unicode等于LPCWSTRwchar_t const *
  2. 在unicode下,你不应该 1 std::string一起工作。它基于char,您将需要基于wchar_t的字符串。
  3. std::wstring基于wchar_t,因此您想要使用它。
  4. 由于参数是正确的const,MessageBox将接受std::wstring::c_str()的结果而不进行投射。
  5. 请注意,代码中的许多强制转换都是不必要的。让我们从:

    开始
    /* convert/cast LPTSTR to LPCWSTR */
    LPCWSTR test = (LPCWSTR) lpCmdLine;
    

    LPCWSTRwchar_t const *,如果您设置了unicode(正如您所见),则LCTSTRwchar_t *。在C ++中添加const隐式转换。所以

    test = lpCmdLine;
    

    也会这样做。通过不选择unicode而不会冒错误,在这种情况下LCTSTR会扩展为char *并且语句将失败并且#34;无法转换为不兼容的指针类型"错误。使用强制转换编译,但由于C风格的强制转换会进行重新解释转换,即将内存内容视为请求的类型,结果是垃圾。

    现在我不明白的是:

    BOOL status = CreateProcess((LPWSTR) LgetGamePath("World of RPG.exe").c_str(), game_args, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation);
    

    函数LgetGamePath得到一个窄字符串(宽文字有L前缀,也可以使用TEXT()宏生成),所以我希望它返回一个狭窄的字符串(你似乎没有显示签名,所以我不确定)。现在你盲目地把它扔到宽处,这将产生垃圾,它不应该能够启动这个过程。另一方面,参数的转换实际上似乎是正确的,只要字符串只是ASCII。

    1 对于可移植程序wchar_t仍然是一团糟,因为它在某些平台上是4个字节而在其他平台上是2个字节(包括急切地创建所有平台版本的窗口)当2个字节足够时接口,当Unicode超过它时被卡住2个字节)。至少对于输入和输出,您通常需要特定的编码,通常是Utf-8(由于它与ASCII的向后兼容性,但Windows不支持它)。在编写可移植程序时,包括我在内的很多人只是准备转换函数来调用系统接口,并在Utf-8(例如Gtk)或Utf-16(存储在uint16_t中,而不是wchar_t中工作。 ,内部也是Qt或ICU。