gpt4 book ai didi

Delphi Unicode 和控制台

转载 作者:行者123 更新时间:2023-12-03 18:38:15 27 4
gpt4 key购买 nike

我正在编写一个与一对硬件传感器接口(interface)的 C# 应用程序。不幸的是,在设备上公开的唯一接口(interface)需要提供用 Delphi 编写的 dll。

我正在编写一个 Delphi 可执行包装器,它调用 DLL 的必要函数并通过 stout 返回传感器数据。但是,此数据的返回类型是 PWideChar(或 PChar),我无法将其转换为 ansi 以便在命令行上打印。

如果我直接将数据传递给 WriteLn,我会得到“?”对于每个字符。如果我查看字符数组并尝试使用 Ansi 转换一次打印一个字符,则只会打印几个字符(尽管它们确实确认了数据),并且它们通常会乱序打印。 (打印时暴露的索引只是跳来跳去。)我还尝试将 PWideChar 转换为整数:'I' 对应于 21321。我可能会找出所有的转换,但有些数据有很多值。

我不确定 dll 使用的是什么版本的 Delphi,但我相信它是 4。肯定在 7 之前。

任何帮助表示赞赏!

TLDR:需要将 UTF-16 PWideChar 转换为 AnsiString 进行打印。

示例应用程序:

program SensorReadout;

{$APPTYPE CONSOLE}

{$R *.res}

uses
Windows,
SysUtils,
dllFuncUnit in 'dllFuncUnit.pas'; //This is my dll interface.

var state: integer;
answer: PChar;
I: integer;
J: integer;
output: string;
ch: char;

begin
try
for I := 0 to 9 do
begin
answer:= GetDeviceChannelInfo_HSI(1, Ord('a'), I, state); //DLL Function, returns a PChar with the results. See example in comments.

if state = HSI_NO_ERRORCODE then
begin
output:= '';
for J := 0 to length(answer) do
begin
ch:= answer[J]; //This copies the char. Originally had an AnsiChar convert here.
output:= output + ch;
end;
WriteLn(output);
end;

except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn(I);
end.`

问题是 PAnsiChar 需要是源自 DLL 的函数的返回类型。

最佳答案

转换 PWideCharAnsiString :

function WideCharToAnsiString(P: PWideChar): AnsiString;
begin
Result := P;
end;

代码从 UTF-16、以 null 结尾的 PWideChar 转换为 AnsiString .如果您在输出中得到问号,那么您的输入不是 UTF-16,或者它包含无法在您的 ANSI 代码页中编码的字符。

我的猜测是,实际发生的情况是您的 Delphi DLL 是使用预 Unicode Delphi 创建的,因此使用 ANSI 文本。但是现在您正试图从后 Unicode Delphi 链接到它,其中 PChar有不同的含义。我确定 Rob 在您的另一个问题中向您解释了这一点。因此,您可以通过声明您的 DLL 导入返回 PAnsiChar 来简单地修复它。而不是 PChar .像这样:
function GetDeviceChannelInfo_HSI(PortNumber, Address, ChNumber: Integer;
var State: Integer): PAnsiChar; stdcall; external DLL_FILENAME;

完成此操作后,您可以按照我上面描述的类似方式分配给字符串变量。

你需要吸收的是在旧版本的 Delphi 中, PCharPAnsiChar 的别名.在现代 Delphi 中,它是 PWideChar 的别名。 .这种不匹配将解释您报告的所有内容。

我确实想到将 Delphi 包装器编写到 DLL 并通过 stdout 与您的 C# 应用程序进行通信是一种非常迂回的方法。我只是直接从 C# 代码 p/invoke DLL。您似乎认为这是不可能的,但这很简单。
[DllImport(@"mydll.dll")]
static extern IntPtr GetDeviceChannelInfo_HSI(
int PortNumber,
int Address,
int ChNumber,
ref int State
);

像这样调用函数:
IntPtr ptr = GetDeviceChannelInfo_HSI(Port, Addr, Channel, ref State);

如果函数返回一个 UTF-16 字符串(这似乎值得怀疑),那么您可以转换 IntPtr像这样:
string str = Marshal.PtrToStringUni(ptr);

或者,如果它实际上是一个对我来说很可能的 ANSI 字符串,那么您可以这样做:
string str = Marshal.PtrToStringAnsi(ptr);

然后当然你会想调用你的DLL来释放返回给你的字符串指针,假设它是在堆上分配的。

关于Delphi Unicode 和控制台,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10046559/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com