2012-04-13 59 views
1

我如何用C该行++?转换一个Delphi代码行C++

用delphi代码(不是这个代码贴在这里)我会写充斥着一些信息,以exe文件,并用C++代码,我会读thhis记录和传递信息的struct

这是记录代码在delphi

​​

C++代码(希望剩下的就是OK)

struct TSettings{ 
    char sFileName[50]; 
    byte siInstallFolder; 
    bool bRunFile; 
    ... 
} Settings; 

... 
DWORD i; 
LPBYTE sZdData; 

     ZeroMemory(&Settings, sizeof(TSettings)); 
     Settings = ????? // im failing here i dunno what to do // i need same as in delphi code above 

和索里我的英文不好.. :(

这是Delphi代码

function GetInfoSettings(FileName: String; // filename from where to get data 
         var lpData: PChar; // where to write data 
         var dwSettingsLen: DWORD // returns the length of all bound files 
         ): Boolean; 
var 
    hFile: THandle; 
    DosHeader: TImageDosHeader; 
    NtHeaders: TImageNtHeaders; 
    SectionHeader: TImageSectionHeader; 
    dwReadBytes, dwOrginalFileSize, dwFileSize, dwSettingsLength: DWORD; 
begin 
    Result := False; 
    hFile := Createfile(PChar(FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0); 
    SetFilePointer(hFile, 0, nil, FILE_BEGIN); 
    ReadFile(hFile, DosHeader, sizeof(DosHeader), dwReadBytes, nil); 
    if dwReadBytes = sizeof(DosHeader) then 
    begin 
    SetFilePointer(hFile, DosHeader._lfanew, nil, FILE_BEGIN); 
    ReadFile(hFile, NtHeaders, sizeof(NtHeaders), dwReadBytes, nil); 
    if dwReadBytes = sizeof(NtHeaders) then 
    begin 
     SetFilePointer(hFile, sizeof(SectionHeader) * (NtHeaders.FileHeader.NumberOfSections -1), nil, FILE_CURRENT); 
     ReadFile(hFile, SectionHeader, sizeof(SectionHeader), dwReadBytes, nil); 
     dwOrginalFileSize := SectionHeader.PointerToRawData + SectionHeader.SizeOfRawData; 
     dwFileSize := GetFileSize(hFile, nil); 
     dwSettingsLength := dwFileSize - dwOrginalFileSize; 
     if dwSettingsLength > 0 then 
     begin 
     SetFilePointer(hFile, dwOrginalFileSize, nil, FILE_BEGIN); 
     GetMem(lpData, dwSettingsLength); 
     ReadFile(hFile, lpData^, dwSettingsLength, dwReadBytes, nil); 
     if dwReadBytes = dwSettingsLength then 
     begin 
      Result := True; 
      dwSettingsLen := dwSettingsLength; 
     end; 
     end; 
    end; 
    end; 
    CloseHandle(hFile); 
end; 

,在这里我得到的信息或绑定的文件...

变种 我,//此处将保存多少字节已经做了.. dwDaSize:DWORD; //所有部分.. dwFilenaam,sFileName后数据的长度:字符串; sZdData:PChar类型; //这里将是“EOF”(所有部分数据完) //该文件将被提取的文件名..毕竟数据

Settings: Tsettings; 


// writting 
    hFile: THandle; 
    lpNumberOfBytesWritten: DWORD; 
begin 
    GetMem(dwFilenaam, MAX_PATH); 
    GetModuleFileName(GetModuleHandle(nil), dwFilenaam, MAX_PATH); 
    if GetInfos(dwFilenaam, sZdData, dwDaSize) then 
    begin 
    i := 0; 
    repeat 

     ZeroMemory(@Settings, sizeof(Tsettings)); 
     settings := Tsettings(Pointer(@sZdData[i])^); 

我尝试(我知道这个代码看起来垃圾LOL)可能不?

bool getSettingsInfo(LPSTR FileName, LPBYTE lpdata, DWORD dwSettingsLen) 
{ 
    HANDLE HandleFile ; 
    DWORD dwReadBytes; 
    DWORD dwOrginalFileSize; 
    DWORD dwFileSize; 
    DWORD dwSettingsLength; 
    PIMAGE_DOS_HEADER pidh ; 
    PIMAGE_NT_HEADERS pinh ; 
    PIMAGE_SECTION_HEADER pish; 

    return false; 
    HandleFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, 0,OPEN_EXISTING,0, NULL); 
    SetFilePointer(HandleFile, 0,0, FILE_BEGIN); 
     ReadFile(HandleFile, pidh, sizeof(pidh), &dwReadBytes,NULL); 
    if (dwReadBytes == sizeof(pidh)) 
    { 
    SetFilePointer(HandleFile, pidh->e_lfanew , NULL, FILE_BEGIN); 
    ReadFile(HandleFile, pidh,sizeof(pinh), &dwReadBytes, NULL); 
    if (dwReadBytes == sizeof(pinh)) 
    { 
     SetFilePointer(HandleFile, sizeof(pish) * (pinh->FileHeader.NumberOfSections -1), NULL, FILE_CURRENT); 
     ReadFile(HandleFile, pish, sizeof(pinh), &dwReadBytes, NULL); 
     dwOrginalFileSize = pish->PointerToRawData + pish->SizeOfRawData; 
     dwFileSize = GetFileSize(HandleFile, NULL); 
     dwSettingsLength = dwFileSize - dwOrginalFileSize; 
     if (dwSettingsLength > 0) 
     { 

     SetFilePointer(HandleFile, dwOrginalFileSize, NULL, FILE_BEGIN); 
     realloc(lpdata, dwSettingsLength); 
     ReadFile(HandleFile, lpdata, dwSettingsLength, &dwReadBytes, NULL); 
     if (dwReadBytes == dwSettingsLength) 
     { 
     return true; 
      dwSettingsLen = dwSettingsLength; 
     } 
     } 
    } 
    } 
    CloseHandle(HandleFile); 
} 

代码提取信息...

DWORD i; // here will be saved how much bytes are already done .. 
    DWORD dwDaSize; // length of data after all sections .. 

    LPSTR dwFilenaam; 
    LPBYTE sZdData; // here will be all data after "EOF" (End of all sections data) 
    LPSTR sFileName;// the filename where the file will be extracted .. 

    char * Installpath; 
    char * buffer; 

    HFILE hFile; 
    DWORD lpNumberOfBytesWritten; 

    memset(dwFilenaam,0, MAX_PATH); 
    GetModuleFileName(GetModuleHandle(NULL), dwFilenaam, MAX_PATH); 
    if (getSettingsInfo(dwFilenaam, sZdData, dwDaSize) == true) 
    { 
     i = 0; 
    // REPEAT 


     ZeroMemory(&Settings, sizeof(TSettings)); 

Settings = ??? 
+1

Delphi短字符串(String [50])的大小为51字节,因为sFileName [0]保存字符串的长度。 – 2012-04-13 23:29:55

+0

为时髦的代码+1。 – 2012-04-13 23:36:51

+0

你需要发布一些你用'...'省略的代码。在某处,内容被赋值为'sZdData',并且有缺失代码中的其他信息。 – 2012-04-13 23:56:01

回答

0
struct TSettings{ 
    uchar length ; // shortstrings have an implicit length byte 
    char sFileName[50]; 
    byte siInstallFolder; 
    bool bRunFile; // one byte, 1=true, 0=false any other value undefined 
    ... 
    } Settings; 


    DWORD i; 
    LPBYTE sZdData; 

    ZeroMemory(&Settings, sizeof(TSettings)); 

    literally it is something like 
    Settings = (struct Settings) (*((void *)&sZDData[i]) 

    essentially it does 

    memcpy (&sZDData[i],&settings,sizeof(TSettings)); 

它所做的是采取sZSdata的第i个元素的地址(@sZDDATA [1]),并将其转换为一个无类型的指针。 (相当于C++(void *))(& sZDData [i])))

然后来了时髦的部分,derefence它(^作为后缀运算符在pascal中,*作为C中的前缀运算符) (void)ptr指向的地址,没有长度数据的内存块)。

当它被分配给设置时,这意味着将该地址中左值(= sizeof(设置))字节的大小移动到左值(设置)的字节数量。

这是一个非常时髦的结构,我不知道我是否已经看到过。我在Delphi和FPC中检查了两个asm级别,他们的表现也一样。

+0

这不是Delphi代码所做的,它不是C++代码应该做的。没有涉及'memcpy';它是由指针'sZdData'引用的内容的直接类型转换为记录。 IOW,它将'TSettings'变量的内容赋给'sZdData [i]地址的内存块(创建一个指向同一位置的类型指针)。根本没有涉及“移动”或“复制”;在发布的代码中,'Settings'和'sZdData [i]'引用同一块内存。 – 2012-04-14 00:00:08

+0

ive addes所有代码mybe它帮助你们了解我需要感谢的答案球员 – user1332636 2012-04-14 00:17:32

+0

请注意,该帖子说“本质上”。这是为了让读者简化它。实际上它是内联代表; movsd + movsw/b语句,如果需要的话,但我不知道如何为C显示,而你的描述是错误的。它分配块/ TO/TSettings值的内容,而不是其他方式。在我看到的代码中(添加之前),没有办法找出szddata指向的内容。我认为这是一个不相关的文件缓冲区。 – 2012-04-14 00:23:16

0

应该比德尔福在C更容易:

typedef struct 
{ 
    uchar length ; // shortstrings have an implicit length byte 
    char sFileName[50]; 
    byte siInstallFolder; 
    bool bRunFile; // one byte, 1=true, 0=false any other value undefined 
    ... 
} TSettings; 

TSettings settings; 
DWORD i; 
LPBYTE sZdData; 

settings = *(TSettings*)(&sZdData[i]); 

这将调用的memcpy,不是铸造的,因为,因为分配TSettings结构。您可以在不复制访问,如果你使用指针TSettings:

TSettings* pSettings; 
DWORD i; 
LPBYTE sZdData; 

pSettings = (TSettings*)(&sZdData[i]); 
printf("%d\n", pSettings->siInstallFolder); // example 

顺便说一句,小心对准。由于项目之间的差距,总体结构尺寸可能会超出您的预期。

+0

Btw几乎所有的32/64位编译器都会在Pascal中接受等价的代码。这个例子很复杂。 – 2012-04-14 11:23:59