Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   C++ zu Delphi funktion umschreiben (https://www.delphipraxis.net/155030-c-zu-delphi-funktion-umschreiben.html)

XXcD 5. Okt 2010 17:44

C++ zu Delphi funktion umschreiben
 
Hallo,
ich habe eine C++ Funktion zum auslesen eines Titels in einer Datei.
Diese müsste ich in Delphi übernehmen, nur komme ich dabei nicht wirklich weiter.
Da ich leider keine Ahnung von C++ habe, bringt mich das zum verzweifeln.

Hier ist mal der Code:
Code:
int parse_cuv(char * file, char *title_name)
{
   FILE *fp;
   
   fp = fopen(file, "rb");
   if (fp != NULL)
      {
      unsigned len, pos, str;
      unsigned char *mem=NULL;

      
      fseek(fp, 0, SEEK_END);
      len=ftell(fp);

      mem= (unsigned char *) malloc(len+16);
      if(!mem) {fclose(fp);return -2;}

      memset(mem, 0, len+16);

      fseek(fp, 0, SEEK_SET);
      fread((void *) mem,len, 1, fp);

      fclose(fp);

      str= (mem[8]+(mem[9]<<8));
      pos=(mem[0xc]+(mem[0xd]<<8));

      int indx=0;

      while(str<len)
         {
         if(mem[str]==0) break;
         
         if(!strcmp((char *) &mem[str], "TITLE"))
            {
            strncpy(title_name, (char *) &mem[pos], 63);
            free(mem);
            return 0;
            }
         while(mem[str]) str++;str++;
         pos+=(mem[0x1c+indx]+(mem[0x1d+indx]<<8));
         indx+=16;
         }
      if(mem) free(mem);
      }

   
   return -1;

}
Ich hoffe mir kann dabei jemand helfen.

Klaus01 5. Okt 2010 21:13

AW: C++ zu Delphi funktion umschreiben
 
Guten Abend,

ein Versuch:

Delphi-Quellcode:
function parse_cuv(fileName: AnsiString; var titleName: AnsiString):Byte;
var
  fp : TMemoryStream;
  i : Integer;
  str : smallInt;
  pos : smallInt;
  value : smallInt;
  idx : Integer;
  s : String;
begin

  fp := TMemoryStream.Create;
  try
    fp.LoadFromFile(fileName);
    fp.Seek(8,soFromBeginning);
    fp.Read(str,2);
    // todo swapBytes(str)
    fp.Seek($c,soFromBeginning);
    fp.Read(pos,2);
    // todo swapBytes(pos)
    idx := 0;
    while str < fp.size do
      begin
         fp.Seek(str,soFromBeginning);
         setLength(s,length('TITLE'));
         fp.Read(s,length('TITLE'));
         if s = 'TITLE' then
           begin
             setLength(titleName,63);
             fp.Read(titleName,63);
             result := 0;
             break;
           end;
        // keine Ahnung was das mir sagen soll.
        //while(mem[str]) str++;str++;
        fp.Seek($1c+idx,soFromBeginning);
        fp.Read(value,2);
        // todo swapBytes(value)
        pos := pos + value;
        inc(idx,16);
      end;

  finally
    fp.free;
  end;
end;
Grüße
Klaus

himitsu 5. Okt 2010 21:17

AW: C++ zu Delphi funktion umschreiben
 
Du kopierst einfach den gesamten Dateiinhalt in "mem" rein und läßt dann folgendes drüberlaufen
Delphi-Quellcode:
var mem: TByteDynArray;
  title_name: AnsiString
  "sonstiges": Integer;

str := mem[8] or (mem[9] shl 8);
pos := mem[12] or (mem[13] shl 8);
indx := 0;
title_name := '';
while str < Length(mem) do
begin
  if mem[str] = 0 then break;
  if not lstrcmpA(@mem[str], 'TITLE') then
  begin
    SetString(title_name, PAnsiChar(@mem[pos]));
    //title_name := Copy(title_name, 1, 63);
    break;
  end;
  while mem[str] <> 0 do inc(str);
  inc(str);
  inc(pos, mem[28 + indx] or (mem[29 + indx] shl 8));
  inc(indx, 16);
end;

// Ergebnis: title_name
hab auch glaich mal das Unicodeproblemchen der API angepaßt
und über das TByteDynArray wurde auch gleich der fehlende Resourcen-Schutzblock kompensiert (das "mem" im C-Code ist ein Pointer, dessen Speicherfreigabe nicht sichergestellt war).

@Klaus01:
- :thumb: für den Resourcenschutzblock
- und unbedingt
Delphi-Quellcode:
S: AnsiString
, da er D2009 nutzt und das Unicode hier bestimmt negative Auswirkungen zeigt
- da, wo du keine Ahnung hast ... den letzen Befehl in eine neue Zeile und schon wird es verständlicher
(Werte/Integer/Bytes in IFs werden als "Boolean" angesehn ... <> 0)
- ich glaub swapBytes ist nicht nötig (Low, High)
- statt SmallInt lieber Word verwenden ... nicht daß man hier eventuell noch in eine Endlosschleife tappt

XXcD 5. Okt 2010 21:49

AW: C++ zu Delphi funktion umschreiben
 
Also ich bekomme den Code noch nicht so ganz zum laufen.

Beim ausführen bekomme ich immer ein Access Violation.

Delphi-Quellcode:
var
stream : TFileStream;
mem: TByteDynArray;
title_name: AnsiString;
indx: integer;
str: word;
pos : word;
begin
   stream := TFileStream.Create(Files,fmOpenRead);
   stream.read(mem,2048);


str := mem[8] or (mem[9] shl 8);
pos := mem[12] or (mem[13] shl 8);
indx := 0;
title_name := '';
while str < Length(mem) do
begin
  if mem[str] = 0 then break;
  if not lstrcmpA(@mem[str], 'TITLE') = 0 then
  begin
    SetString(title_name, PAnsiChar(@mem[pos]), Sizeof(mem));
    //title_name := Copy(title_name, 1, 63);
    break;
  end;
  while mem[str] <> 0 do inc(str);
  inc(str);
  inc(pos, mem[28 + indx] or (mem[29 + indx] shl 8));
  inc(indx, 16);
end;
end;

Edit: Ich nutze Delphi 2007, hatte nen paar Probleme mit OpenGL in der 2009 Version.

Luckie 5. Okt 2010 21:51

AW: C++ zu Delphi funktion umschreiben
 
Zitat:

Zitat von XXcD (Beitrag 1053996)
Beim ausführen bekomme ich immer ein Access Violation.

Und wo?

XXcD 5. Okt 2010 21:53

AW: C++ zu Delphi funktion umschreiben
 
An dieser Stelle:

Delphi-Quellcode:
str := mem[8] or (mem[9] shl 8);

himitsu 5. Okt 2010 22:15

AW: C++ zu Delphi funktion umschreiben
 
Ist die Datei auch 2048 Byte groß?

Und es wäre nicht schlecht, wenn man "mem" etwas Speicher gibt (SetLength), bevor man da versucht war reinzuspeichern (read).

(Wobei ich hier des Zugriffsverletzung schon beim read erwartet hätte.)

Wegen D2009/D2007 ... da die Datei so oder so Ansi ist, sollte man den Code dennoch auf AnsiString auslegen.
Denn sonst gibt es mal Probleme, wenn sich doch irgendwann mal überlegt dieses auf D2009+ zu portieren.

Neutral General 5. Okt 2010 22:15

AW: C++ zu Delphi funktion umschreiben
 
Man sollte vorher Speicher für das Array reservieren:

Delphi-Quellcode:
SetLength(mem,2048);
Und das Einlesen muss so aussehen:

Delphi-Quellcode:
stream.read(mem[0],2048);

XXcD 5. Okt 2010 22:22

AW: C++ zu Delphi funktion umschreiben
 
Ok das funktioniert.
Vielen Dank schonmal, nur wird der Titel nicht komplett ausgelesen, da stehen dann nur die ersten 4 Buchstaben.

himitsu 5. Okt 2010 22:42

AW: C++ zu Delphi funktion umschreiben
 
Zitat:

Zitat von XXcD (Beitrag 1054002)
Vielen Dank schonmal, nur wird der Titel nicht komplett ausgelesen, da stehen dann nur die ersten 4 Buchstaben.

Sizeof(mem) = 4 ... also 4 Byte/Zeichen

stattdessen mal
Delphi-Quellcode:
lstrlen(PAnsiChar(@mem[pos]))
versuchen
oder diesen Parameter weglassen (ich dachte so würde SetString bis zur #0 lesen)

oder doch mal 63 dort versuchen, aber ich bin mir nicht sicher, ob SetString dann auch bei der #0 aufhört.


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:47 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz