我在使用delphi从DEV_BROADCAST_PORT获取友好名称(dbcp_name)时遇到问题。
我尝试过使用microsoft帮助文档,它说它是一个指向空终止字符串的指针,但在该页面上有一条注释表明它是一个可变长度的结构,而dbcp_name是一个包含实际数组的数组端口名称的字符。
我试图提取这个,但我目前还没有找到方法,因为当我得到它返回任何它是完全乱码。
我使用的代码如下:
PDevBroadcastPort = ^DEV_BROADCAST_PORT;
DEV_BROADCAST_PORT = packed record
dbcp_size : DWORD ;
dbcp_devicetype : DWORD;
dbcp_reserved : DWORD ;
dbcp_name : array[0..0] of ansichar; //TCHAR dbcp_name[1]; not valid
end;
我已经为数组的长度尝试了不同的值,我曾在某处读过这是正确的声明,但我并不完全确定。注释掉的行也是微软文档为C ++中的行提供的内容
要提取我尝试过的信息:
var
PData: PDevBroadcastPort;
FName: string;
...
PData := PDevBroadcastPort(Msg.lParam);
ShowMessage('Length '+Inttostr(length(PData^.dbcp_name)));
FName := '';
i:=0;
while((PData^.dbcp_name[i]) <> #0) and (i < 100) do
begin
FName := FName + (PData.dbcp_name[i]);
i := i +1;
ShowMessage(FName);
end;
我已经尝试将while循环设置为以数据结构的长度终止,但如果我不设置它,那么它就会变得很大。
任何帮助都表示赞赏,如果我遗漏了此问题所需的任何代码,请告诉我,我会尽快获得。
由于
答案 0 :(得分:4)
文档没有说它是一个以空字符结尾的字符串的指针;它说它是一个以空字符结尾的字符串。这对于在长度只有一个元素的记录末尾声明的数组来说是典型的。
在指定的记录大小之后实际上有更多的内存,并且该内存保存字符串的剩余字符。指向该记录字段的指针也是指向字符数据的指针。
FName := PAnsiChar(@PData.dbcp_name);
您的数组遍历代码也应该可以正常工作,假设您已经为该段代码禁用了边界检查(否则当程序检测到您读取超出数组的第一个元素时,您将获得异常)。 p>
所有这些都预先假定PData
确实是指向Dev_Broadcast_Port
结构的指针。你没有提供任何关于你正在传递什么信息的信息,所以我不知道你是否真的拥有你认为的信息。
如果您使用的是Delphi 2009或更高版本,则C声明中的TCHAR
类型等同于Delphi的WideChar
类型。将字段解释为AnsiChar
数组会得到错误的结果,尽管对于大多数端口名称,它可能看起来好像数组是一个以空字符结尾的单字符字符串列表。除非您确定自己拥有非Unicode数据,否则只需使用Char
和PChar
,并让Delphi版本确定您拥有的数据类型。
FName := PChar(@PData.dbcp_name);
答案 1 :(得分:0)
dbcp_name
字段包含实际字符。字符数据的长度减去空终止符,为dbcp_size - SizeOf(DEV_BROADCAST_PORT)
,因此您可以像这样获取名称:
type
DEV_BROADCAST_PORTA = packed record
dbcp_size : DWORD;
dbcp_devicetype : DWORD;
dbcp_reserved : DWORD;
dbcp_name : array[0..0] of AnsiChar;
end;
DEV_BROADCAST_PORTW = packed record
dbcp_size : DWORD;
dbcp_devicetype : DWORD;
dbcp_reserved : DWORD;
dbcp_name : array[0..0] of WideChar;
end;
{$IFDEF UNICODE}
DEV_BROADCAST_PORT = DEV_BROADCAST_PORTW;
{$ELSE}
DEV_BROADCAST_PORT = DEV_BROADCAST_PORTA;
{$ENDIF}
PDEV_BROADCAST_PORT = ^DEV_BROADCAST_PORT;
var
PData: PDEV_BROADCAST_PORT;
FName: string;
...
PData := PDEV_BROADCAST_PORT(Msg.lParam);
SetString(FName, PData^.dbcp_name, (PData^.dbcp_size - SizeOf(DEV_BROADCAST_PORT)) div SizeOf(Char));
ShowMessage(FName);