我理解它的作用:将字符串文字指定为const wchar_t *
(宽字符串)而不是const char *
(普通旧字符),但它是如何实际定义的?
它是某种宏吗?它是GCC编译器的运算符吗?这是什么?
David对另一个问题的回答显示Delphi DLL函数返回一个WideString.我从没想过如果没有使用它是可能的ShareMem
.
我的测试DLL:
function SomeFunction1: Widestring; stdcall;
begin
Result := 'Hello';
end;
function SomeFunction2(var OutVar: Widestring): BOOL; stdcall;
begin
OutVar := 'Hello';
Result := True;
end;
Run Code Online (Sandbox Code Playgroud)
我的来电计划:
function SomeFunction1: WideString; stdcall; external 'Test.dll';
function SomeFunction2(var OutVar: Widestring): BOOL; stdcall; external 'Test.dll';
procedure TForm1.Button1Click(Sender: TObject);
var
W: WideString;
begin
ShowMessage(SomeFunction1);
SomeFunction2(W);
ShowMessage(W);
end;
Run Code Online (Sandbox Code Playgroud)
它有效,我不明白怎么做.我所知道的约定是Windows API使用的约定,例如Windows GetClassNameW
:
function GetClassNameW(hWnd: HWND; lpClassName: PWideChar; nMaxCount: Integer): Integer; stdcall;
Run Code Online (Sandbox Code Playgroud)
意味着调用者提供缓冲区和最大长度.Windows DLL以长度限制写入该缓冲区.调用者分配和释放内存.
另一种选择是DLL分配内存,例如通过使用LocalAlloc
,并且调用者通过调用释放内存LocalFree
.
内存分配和解除分配如何与我的DLL示例一起使用?"魔法"是否会发生,因为结果是WideString
(BSTR …
我找到了一个Windows API函数,它执行字符串的"自然比较".它的定义如下:
int StrCmpLogicalW(
LPCWSTR psz1,
LPCWSTR psz2
);
Run Code Online (Sandbox Code Playgroud)
要在Delphi中使用它,我这样说:
interface
function StrCmpLogicalW(psz1, psz2: PWideChar): integer; stdcall;
implementation
function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';
Run Code Online (Sandbox Code Playgroud)
因为它比较了Unicode字符串,所以当我想比较ANSI字符串时,我不确定如何调用它.似乎足以将字符串转换为WideString然后转换为PWideChar,但是,我不知道这种方法是否正确:
function AnsiNaturalCompareText(const S1, S2: string): integer;
begin
Result := StrCmpLogicalW(PWideChar(WideString(S1)), PWideChar(WideString(S2)));
end;
Run Code Online (Sandbox Code Playgroud)
我对字符编码知之甚少,所以这就是我提问的原因.这个函数是OK还是我应该首先以某种方式转换两个比较的字符串?
我们可以在Unix编译器中使用wmain()函数,还是只在\ for windows上使用?
我有一个用Delphi编写的dll和测试应用程序.测试应用程序使用多个线程来调用dll导出的函数.导出的函数具有简单的线程安全实现.运行测试应用程序时会发生各种错误(访问冲突,无效指针操作,堆栈溢出等)或应用程序冻结.在某些情况下,应用程序完成没有错误.
请注意,这些错误仅在使用多个线程时发生(表面).从主线程调用函数时,一切正常.
我发现将ShareMem添加到dll和应用程序会停止所有这些错误.但我不明白为什么.据我所知,只有在dll和应用程序之间传递长字符串时才需要ShareMem.据我所知,WideString不是一个长字符串.
另外根据这篇文章,不应该要求ShareMem: 为什么Delphi DLL可以在不使用ShareMem的情况下使用WideString?
这是dll的来源:
library External;
uses
Winapi.Windows;
type
TMyType = class
private
FText: string;
end;
function DoSomething(input: WideString; out output: WideString): Bool; stdcall;
var
x: TObject;
begin
x := TMyType.Create;
try
output := x.ClassName;
finally
x.Free;
end;
Result := True;
end;
exports
DoSomething;
begin
end.
Run Code Online (Sandbox Code Playgroud)
这是测试应用程序:
program ConsoleTest;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
Winapi.Windows,
OtlParallel;
function DoSomething(input: WideString; out output: WideString): Bool; stdcall; external 'External.dll' name 'DoSomething';
var
sResult: WideString;
begin
try
Parallel.&For(0, 500).Execute(procedure(value: Integer)
var
sResult: …
Run Code Online (Sandbox Code Playgroud) 我们目前正在将Delphi 2007项目转换为Delphi 2010.我们已经在使用Unicode(通过WideStrings和TNT Unicode控件).
我期望将所有Wide函数(例如WideUpperCase)替换为等效的,例如UpperCase,但它们的工作方式不同.例如,WideUpperCase与UpperCase的工作方式不同.WideUpperCase正确地改变了Campañas,但是UpperCase以小写形式留下了ñ.
我应该注意哪些其他差异?例如,WideFormat和Format的工作原理是一样的吗?
谢谢
我想用wcout显示混有中文的阿拉伯语消息.
以下代码没问题:
#include <iostream>
using namespace std;
int main()
{
wcout.imbue(locale("chs"));
wcout << L"??"; // OK
}
Run Code Online (Sandbox Code Playgroud)
但是,以下代码不起作用:
#include <iostream>
using namespace std;
int main()
{
wcout.imbue(locale(/* What to place here ??? */));
wcout << L"???????????? ?????????????"; // Output nothing. VC++ 2012 on Win7 x64
// Why does the main advantage of unicode not apply here?
}
Run Code Online (Sandbox Code Playgroud)
我认为在采用unicode之后应该弃用代码页的概念.
Q1.wout显示这样一个文本的机制是什么?
Q2.为什么Windows作为基于unicode的操作系统不支持在其控制台窗口中输出unicode字符?
我的代码基本上是这样的:
wstring japan = L"??";
wstring message = L"Welcome! Japan is ";
message += japan;
wprintf(message.c_str());
Run Code Online (Sandbox Code Playgroud)
我希望使用宽字符串,但我不知道它们是如何输出的,所以我使用了wprintf.当我运行如下的东西时:
./widestr | hexdump
Run Code Online (Sandbox Code Playgroud)
十六进制代码点创建了这个:
65 57 63 6c 6d 6f 21 65 4a 20 70 61 6e 61 69 20 20 73 3f 3f
e W c l m o ! e J p a n a i s ? ?
Run Code Online (Sandbox Code Playgroud)
为什么他们都按顺序跳了?我的意思是如果wprintf是错的,我仍然不明白为什么它会以这样一个特定的混乱顺序输出!
编辑:endianness还是什么?他们似乎旋转每两个字符.呵呵.
编辑2:我尝试使用wcout,但它输出完全相同的十六进制代码点.奇怪的!
如何在C++中将wchar_t字符串从大写转换为小写?
该字符串包含日语,中文,德语和希腊字符的混合.
我想过使用towlower ......
http://msdn.microsoft.com/en-us/library/8h19t214%28VS.80%29.aspx
..但文件说:
towlower的案例转换是特定于语言环境的.只有与当前区域设置相关的字符才会被更改.
编辑:也许我应该描述我在做什么.我收到用户的Unicode搜索查询.它最初采用UTF-8编码,但我将其转换为widechar(我的措辞可能不对).我的调试器(VS2008)在"可变快速监视"中正确显示日语,德语等字符.我需要在Unicode中查看另一组数据并查找搜索字符串的匹配项.虽然当搜索区分大小写时,这对我来说没有问题,但是在不区分大小写的情况下更难以解决问题.我(可能是天真的)解决问题的方法是将所有输入数据和输出数据转换为小写,然后进行比较.
我正在使用 swprintf 将字符串构建到缓冲区中(使用循环等)。
const int MaxStringLengthPerCharacter = 10 + 1;
wchar_t* pTmp = pBuffer;
for ( size_t i = 0; i < nNumPlayers ; ++i)
{
const int nPlayerId = GetPlayer(i);
const int nWritten = swprintf(pTmp, MaxStringLengthPerCharacter, TEXT("%d,"), nPlayerId);
assert(nWritten >= 0 );
pTmp += nWritten;
}
*pTaskPlayers = '\0';
Run Code Online (Sandbox Code Playgroud)
如果在测试期间断言从未命中,我可以确定它永远不会在实时代码中命中吗?也就是说,我是否需要检查 nWritten < 0 并处理它,还是我可以安全地假设不会有问题?
什么情况下可以返回-1?文档或多或少只是说明“如果功能失败”。在一个地方,我读到如果它不能匹配参数(即格式化字符串与可变参数),它将失败,但这并不让我担心。
在这种情况下,我也不担心缓冲区溢出 - 我知道缓冲区足够大。