AS,你最好把这些问题放在rsdn.ru论坛上,我觉得他们对新手更加宽容,而不是DelphiMasters。
Gu,基本上,你只需要阅读Delphi XE2的手册。所有的东西都在那里,只要用思考和注意力去阅读。
1)你根本不应该制作DLL。你应该制作BPL。
DLL旨在与纯C接口(如Win32 API)协作。
这些是最原始的类型,没有任何副作用。
C被称为“机器无关”的汇编语言,因为它的原始性,而DLL接口就是其中一种。
DLL可以用于与其他语言的兼容性,因为它们使用与Delphi不兼容的另一种副作用。然后,DLL强制执行最原始的协作,从接口中删除所有副作用。通过将互通级别降低到最简单的类型,DLL接口强制实现兼容性。
但是,当您需要与Delphi交互时,最好让Delphi关心所有兼容性问题。这就是Delphi 3中BPL的用途。
对于此类情况,使用DLL没有任何理由。
当然,如果你愿意的话,你可以自己给自己脚射击。
https://forums.embarcadero.com/thread.jspa?threadID=64114
2) 在XE2中,你不应该使用WideString,而应该使用UnicodeString。
字符串手册特别强调了这一点。所以看起来你只是没有阅读手册。
3) 字符串常量是Unicode的。(但字符常量是随机的ANSI或Unicode,这会导致意外的行为错误)。
并且没有必要询问和相信任何人的话 - 只需在任何查看器中打开你的exe文件并搜索这些常量,你会发现它们以2字节的UCS-2(也称为WideChar)编码存在。
4) Unicode BOM用于确定CPU的字节顺序,是Intel还是Motorola风格。
当你开发Windows时,你只能有Intel字节顺序,所以不需要BOM。
5) 你所写的关于长度和内存大小的整个段落非常模糊。你所说的长度是什么意思,以哪种单位衡量,从哪里获取?
我假设你所说的长度是指不包括任何“幕后”服务结构/字符的字符数。这就是内置函数System.Length(字符串或数组)返回的内容。
但是,如果这个假设是错误的,那么下面的答案也就错了。
而问题是你是否应该乘以2只是糟糕代码的一个标志。
你应该总是乘以某些东西,几年前你已经应该乘以。
乘以...什么?通过SizeOf(使用的char变量)或SizeOf(使用的char类型)。
然后t将是Delphi自动确定需要多少内存。
并且在处理C字符串时,您应该使用的不是length,而是length+1-不要忘记#0终止符。
6)我们应该如何处理不同Windows代码页中的ANSI字符串?如果我们收到一个代码页为1200的ANSI字符串,我们应该重新编码字符串还是按原样处理?
RTFM!!!
只需声明带有代码页1200的AnsiString类型。
或使用RawByteStrnig和SetCodePage。
请阅读下面的真实代码。
再次强调,RTFM - 所有这些都在内置帮助中描述。
在Delphi XE2的内置帮助中阅读所有这些只需要2个小时。
7) 如何使用TEncoding类在Unicode、UTF-8、WideString和AnsiString类之间进行转换? TEncoding是为TStringList或类似对象设计的。
为什么要这样做?有UTF8String类型 - 直接使用即可。
var as: AnsiString; ucs2s: string; utf8string: UTF8String;
... as := ucs2; utf8s := as; ....
8) 使用宽字符串或Unicode字符串是否会有严重的性能损失?
这取决于你指的是哪种“Unicode”,UCS-2还是UTF8。以及你想使用哪些操作。
只需编写一个长循环并测量时间即可。
9) 我们应该将接口编写成需要PChar、PAnsiChar和PWideChar参数类型的长度参数吗?
由你决定,随意处理。
通常PChar是以#0结尾的C字符串。这就是StrLen函数的工作方式。
如果您忽略这个约定并像不带类型的指针一样使用它 - 那么请单独传递长度。
所有这些问题都已经在帮助文件中得到了回答!!!请阅读它。
function CDF_File_Buffer.GetStringNoBounds(const ofs, len: integer): string;
var cntDOS, cntWin, cntWeird, i : Cardinal;
sBuf: RawByteString; cp: word;
ptr, ptr_i: PAnsiChar;
const rusDOS: set of AnsiChar = [#$80..#$AF, #$E0..#$F1];
rusWin: set of AnsiChar = [#$C0..#$FF];
begin
ptr := Pointer(Header); Inc(ptr, ofs);
case textCharset of
tcsGuess:
begin
ptr_i := ptr; cntDOS :=0; cntWin :=0; cntWeird:=0;
for i := 1 to len do begin
if ptr_i^ in rusDOS then Inc(cntDOS);
if ptr_i^ in rusWin then Inc(cntWin);
if (ptr_i^ < #32) or ((ptr_i^ >= #127) and not(ptr_i^ in rusWin) and not(ptr_i^ in rusDOS))
then inc(cntWeird);
Inc(ptr_i);
end;
if (cntWin > cntDOS) or (cntWeird > cntDOS) then cp := 1251 else cp := 866;
end;
tcsWin: cp := 1251;
tcsDOS: cp := 866;
else cp := 0;
end;
SetString(sBuf,ptr,len);
for i := 1 to Length(sBuf) do if sBuf[i] = #0 then sBuf[i] := #7;
SetCodePage(sBuf, cp, false);
Result := string(sBuf);
end;
function CDF_File_Buffer.GetString(const ofs, len: integer; const min, max: integer): string;
begin
if (ofs <= 0) or (len <= 0) then
Exit( '--- нет текста ---');
if Cardinal(ofs + (len-1)) >= TotalSize then
Exit('--- За пределами файла ---');
Result := '--- За пределами допустимой области: слишком близко к ';
if ofs < min then Exit(Result + 'началу ---');
if ofs + (len-1) > max then Exit(Result + 'концу ---');
Result := GetStringNoBounds(ofs, len);
end;
function CDF_File_Buffer.GetString(const ofs, len: integer): string;
begin
Result := GetString(ofs, len, 0, TotalSize-1);
end;