2010-07-31 141 views
1

有人可以告诉我在哪里,我在转换犯错误:C到德尔福转换

C:

typedef struct _REGISTRY_EVENT { 
    REG_NOTIFY_CLASS eventType; 
    TIME_FIELDS time; 
    HANDLE processId; 
    ULONG dataType; 
    ULONG dataLengthB; 
    ULONG registryPathLengthB; 
    /* Contains path and optionally data */ 
    UCHAR registryData[]; 
} REGISTRY_EVENT, * PREGISTRY_EVENT; 

德尔福:

_Registry_Event = record 
    EventType: REG_NOTIFY_CLASS; 
    Time: TIME_FIELDS; 
    processID: THandle; 
    DataType: ULONG; 
    DataLength: ULONG; 
    registryPathLength: ULONG; 
    registryData: array of UCHAR; 
end; 

从C代码的sizeof(REGISTRY_EVENT) = 36

from delphi code sizeof(REGISTRY_EVENT)= 40

在此先感谢

博扬

+1

订货号用4个空间,以便它得到语法highlighing和等宽字体的代码类型。这样就容易多了。 – zz1433 2010-07-31 18:34:23

回答

7

的错误是在这里

registryData: array of UCHAR; 

你并不需要一个动态数组在这里。


更新:

我假定

UCHAR registryData[]; 

是C劈在结构的端部以产生一个零长度字段。等效德尔福黑客是

registryData: record end; 

访问此虚拟场作为德尔福数组,你应该强制转换:

type 
    PByteArr = ^TByteArr; 
    TByteArr = array[0..$FFFF] of Byte; 

    PRec = ^TRec; 
    TRec = packed record 
    Data: Integer; 
    MoreData: record end; 
    end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    P: PRec; 
    PMoreData: PByteArr; 

begin 
    P:= AllocMem(SizeOf(TRec) + 4); 
    PMoreData:= @P^.MoreData; 
    PMoreData^[2]:= 3; 
    ShowMessage(IntToStr(PMoreData^[2])); 
    FreeMem(P); 
end; 

,但可能需要强制转换这个虚拟场到别的东西,因为字段定义只是一个黑客。而转换C结构对Delphi;

最后::从不使用Delphi动态数组(UCHAR的阵列等registryData)。 Delphi中的动态数组是一种生命周期管理的参考类型,在C中没有完全等效的参考类型

+0

RegistryData:char数组 uchar的registrydata:array [0..0] registrydata:uchar 所有大小都为40 – 2010-07-31 20:27:14

+0

Bojan:删除C中的uchar数组,并查看大小是否更改。 如果不是,那就是问题所在。 sizeof(x)= 0只有一种类型,即“记录结束”;并且pascal有一个没有等价的长度为零的数组。 IOW这种C语法是以C为中心的黑客攻击。 – 2010-07-31 22:36:09

+0

非常感谢所有人。使用空记录我解决了这个问题。这c结构,甚至RegistryData有更多然后20​​0宽字符的大小总是= 36. – 2010-08-01 05:18:09

2

我不知道这是一个错误 - 它可能是编译器插入域之间的一些填充。尝试在记录定义之前添加{$Align off},或将= Record更改为= Packed Record并查看是否有帮助。

编辑:虽然这也可能是一个问题,但@塞尔格的答案让我感觉更有可能。

+0

和{$关闭}并打包记录会导致错误的结果。 与记录,为时间我接收年= 0,月= 2010年,日= 7,小时= 31,分= 22等但事件类型和进程ID是正确的。 – 2010-07-31 20:20:36

+0

这是从内核驱动程序返回的用于注册表监视的结构。在registryData中存储注册表路径,数据等,并用dataLength,registryPathLengthB定义注册表数据中使用的字节。 – 2010-07-31 20:21:01

+0

在读取此代码的c代码是 UINT offset = 0;注册表数据首先包含注册表路径,然后可选地包含一些数据* PREGISTRY_EVENT e =(PREGISTRY_EVENT)(registryEventsBuffer + offset); BYTE * registryData = NULL; wchar_t * szRegistryPath = NULL; szRegistryPath =(wchar_t *)malloc(e-> registryPathLengthB); CopyMemory(szRegistryPath,e-> registryData,e-> registryPathLengthB); ... offset + = sizeof(REGISTRY_EVENT)+ e-> registryPathLengthB + e-> dataLengthB; 当我在delphi中减少前一行4我正在接收事件链。 – 2010-07-31 20:22:19

0

这可能是由于每个字段的数据类型的大小不同或者由于不同的填充引起的。对于字段大小,为每个字段打印sizeof()或size(),并进行比较。如果它们完全相同,那么它是填充,并且您可能需要找到一个编译器选项来调整它。

也就是说,如果你在乎。为什么你在意尺寸是否相同?

+1

有人猜测,他关心的是因为这个结构将被操作系统返回,而错误的大小意味着他的某些字段不会与操作系统发送的内容重合。 – 2010-07-31 18:44:25

1
UCHAR registryData[]; 

registryData: array[0..0] of UCHAR; 

具有压缩记录和堆积阵列为_Registry_Event的大小等于34

+0

大小 REG_NOTIFY_CLASS; = 4 TIME_FIELDS; = 16 THandle; = 4 3 x ULONG; 3×4 = 12 UCHAR; = 4 Sum = 40 not 34 – 2010-08-01 06:03:25

+0

如果REG_NOTIFY_CLASS是4个字节,则_Registry_Event的大小等于37. 请注意,UCHAR的数组[0..0]等于1个字节而不是4个。 – pani 2010-08-01 06:52:33