【问题标题】:LPTSTR contains only one letterLPTSTR 只包含一个字母
【发布时间】:2016-02-23 11:56:12
【问题描述】:

我正在为应用程序创建一个 DLL。应用程序调用 DLL 并接收长度为 8 到 50 的字符串。

我遇到的问题是只显示应用程序收到的任何消息的第一个字母

下面是GetMethodVersion函数。

#include "stdafx.h"
STDAPI_(void) GetMethodVersion(LPTSTR out_strMethodVersion, int in_intSize)
{
   if ((int)staticMethodVersion.length() > in_intSize)
       return;
   _tcscpy_s(out_strMethodVersion, 12, _T("Test")); 
   //staticMethodVersion should be insted of _T("Test")
}

项目设置设置为 Unicode。 经过一些研究,我相信 Unicode 格式及其功能存在问题。感谢您提供的任何帮助。

【问题讨论】:

  • 为什么代码中有out_strMethodVersionstaticMethodVersionout_String三个字符串?
  • 对不起,删除了一堆不必要的代码,一定错过了重命名
  • 您在哪里看到单个字母,在 Visual Studio 的一个调试窗口中,或者在控制台或应用程序的 GUI 中?也许字符串是 Unicode,但 Visual Studio 认为它不是?直接看内存中的字符串,看看有没有其他用00字节分隔的字母。
  • 问题是我们必须在这里猜测很多,因为提供的示例不完整。给我们一个示例,我们可以粘贴并编译并观察问题(首先像我们一样自己编译示例,并确认问题在示例中仍然存在,就像在您的原始代码中一样)。

标签: c++ dll unicode lptstr lpwstr


【解决方案1】:

您在问题中写道,项目设置是 Unicode:对于 DLL 和调用 EXE 是否都是这样?确保它们都匹配。

在 Unicode 构建中,丑陋的 TCHAR 宏变成:

LPTSTR      --> wchar_t*
_tcscpy_s   --> wcscpy_s
_T("Test")  --> L"Test"

所以你有:

STDAPI_(void) GetMethodVersion(wchar_t* out_strMethodVersion, 
                               int in_intSize)
{
    ...
    wcscpy_s(out_strMethodVersion, 12, L"Test");
}

你确定“幻数” 12 是正确的吗? out_strMethodVersion 指向的目标字符串缓冲区大小是否至少为 12 wchar_ts(包括终止 NUL)?

然后,查看通话站点(您没有显示)。

如何打印返回的字符串?也许您正在使用 ANSI char 函数,因此返回的字符串被误解char* ANSI 字符串,因此Unicode UTF-的第一个0x00 字节16 字符串在调用站点被误解为 NUL 终止符,并且字符串在打印时在第一个字符处被截断?

 Text:             T       e       s       t      NUL
 UTF-16 bytes:   54 00   65 00   73 00   74 00   00 00
     (hex)          **<--+
                         |
                 First 00 byte misinterpreted as 
               NUL terminator in char* ANSI string,
         so only 'T' (the first character) gets printed.

编辑

您在 cmets 中阐明的事实是:

我将 DLL 切换为 ANSI,EXE 显然也是如此,尽管 exe 被记录为 Unicode。

让我觉得 EXE 采用 UTF-8 Unicode 编码。

就像在 ANSI 字符串中一样,UTF-8 中的 0x00 字节是字符串 NUL 终止符,所以前面对 UTF-16 的分析 0x00 字节(在 wchar_t 中)误解了 作为字符串 NUL 终止符适用。

请注意,纯 ASCII 是 UTF-8 的正确子集:因此,如果您只使用纯 ASCII 字符(如"Test")并将它们传递给 EXE,您的代码可能会工作。

但是,如果记录的 EXE 使用 Unicode UTF-8,您可能需要做正确的事并从 DLL 返回一个 UTF-8 字符串。

字符串通过char*(对于 ANSI 字符串)返回,但重要的是确保 UTF-8 是 DLL 用于返回该字符串的编码,以避免未来会出现一些细微的错误。

虽然在 Windows API 和 Visual Studio 中使用的通用术语是 “Unicode”,但它实际上表示这些上下文中的 UTF-16 Unicode 编码。

但是,UTF-16 并不是唯一可用的 Unicode 编码。例如,为了在 Internet 上交换文本,UTF-8 编码被广泛使用。在您的情况下,听起来您的 EXE 需要一个 Unicode UTF-8 字符串。

【讨论】:

  • 你的帖子让我思考。到目前为止,我一直假设调用 exe 是未编码的,因为它是这样记录的。但是切换到 ANSI 修复了它!
  • @PonWer 也许调用者使用的是 UTF-8 而不是 UTF-16?切换到 ANSI 解决了问题的事实意味着调用者肯定没有使用 UTF-16。
  • @PonWer:你到底是怎么切换到 ANSI 的? DLL和调用EXE?或者您是否有一个 Unicode (UTF-16) DLL 和一个使用 ANSI/MBCS 构建的 EXE?请澄清。确保 DLL 和调用 EXE 都使用 same 文本格式进行通信,或者在边界处提供正确的转换。正如您在@RaymondChen 的评论中看到的那样,有不同的 Unicode 编码,例如UTF-8 和 UTF-16。我在回答中假设 "Unicode == UTF-16" (这是 Visual Studio 中的一般假设,_UNICODE/UNICODE 预处理器宏等)。
  • 我将 dll 切换为 ANSI,exe 显然也是如此,尽管 exe 被记录为 unicode。
【解决方案2】:

#include "stdafx.h" 之后到#define UNICODE 为时已晚。它应该在stdafx.h 本身的第一个#include 之前定义。但正确的方法是在项目属性中设置(菜单项目>属性>配置属性>常规>字符集>“使用Unicode字符集”)。

【讨论】:

  • 好的,谢谢,我在项目设置中更改了它,但问题仍然存在
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-08
  • 2015-07-06
  • 1970-01-01
  • 2013-11-26
  • 2011-07-11
  • 1970-01-01
  • 2015-03-28
相关资源
最近更新 更多