Alte .lib aus BCB6 in CG2009



  • Hatte auch so ein Problem bei der Portierung einer lib,
    habe dann aus der lib eine DLL gemacht und greife nun
    über die DLL auf die Funktionen zu.



  • VergissEs schrieb:

    habe dann aus der lib eine DLL gemacht und greife nun
    über die DLL auf die Funktionen zu.

    Selbst damit verläßt du dich darauf, daß die Implementation von AnsiString auf beiden Seiten gleich ist, was keineswegs immer der Fall sein muß. Mit der Unicode-Umstellung wurde z.B. die internen Felder (untergebracht bei negativen Indizes; für Details siehe AnsiString::StrRec) angepaßt. Ich bin nicht sicher, was passiert, wenn die String-Checks, die C++Builder >=2009 durchführt, auf einem AnsiString durchgeführt werden, der die internen Felder alten Stils besitzt, aber es dürfte nicht besonders hübsch sein.

    Viel schlimmer wird das natürlich, wenn zusätzlich noch STL-Typen verwendet werden: C++Builder 6 verwendet STLport, alle nachfolgenden Versionen bis einschließlich 2010 enthalten Dinkumware; die beiden sind natürlich grundsätzlich inkompatibel.

    Merke: zwischen Modulen, die mit verschiedenen Compilern oder auch nur abweichenden Compilerversionen erstellt wurden, nur über C-Interfaces kommunizieren. Das gilt für alle Arten der Module, also für Objektdateien (.obj) und Sammlungen derselben (.lib) gleichermaßen wie für DLLs.

    Die saubere Lösung ist natürlich, die Bibliotheken mit C++Builder 2009 zu übersetzen. Woran scheitert das?



  • Im meinem Fall ist es die Jedi Komponente
    TJvZlibMultiple die Ihren Dienst nicht mehr unter 2009 tut.



  • VergissEs schrieb:

    Im meinem Fall ist es die Jedi Komponente
    TJvZlibMultiple die Ihren Dienst nicht mehr unter 2009 tut.

    Deshalb machst du dir derartige Umstände? Du könntest einfach den Code in JvZlibMultiple.pas anpassen; wie hier und hier unter anderem beschrieben wird, dürfte es schon ausreichen, überall dort, wo Strings in die einzelnen Bytes zerlegt oder in Streams geschrieben werden (also dort, wo SizeOf(Char)=1 impliziert wird), Char durch AnsiChar und String durch AnsiString zu ersetzen. Und wenn es funktioniert, könntest du den Bug sowie einen Workaround in den JEDI Issue Tracker eintragen, dann werden deine Änderungen auch in die offizielle JVCL-Revision aufgenommen.



  • Ja ich machte mir diese Umstände weil ich Gewährleisten muss das schon
    bestehende Archive auch weiterhin gelesen werden müssen.
    Und da ich meine Anwendungen komplett auf UnicodeString
    umgestellt habe kommt auch nicht ein

    Char durch AnsiChar und String durch AnsiString zu ersetzen

    in Frage.



  • VergissEs schrieb:

    Und da ich meine Anwendungen komplett auf UnicodeString
    umgestellt habe kommt auch nicht ein

    Char durch AnsiChar und String durch AnsiString zu ersetzen

    in Frage.

    Das sollte davon nicht tangiert werden. In diesem Fall ist es ja kein Quick&Dirty-Fix, sondern die Komponente benutzt Strings anstelle von Byte-Arrays. Und da sind nunmal AnsiStrings richtig, da ihre Elementgröße 1 ist.



  • audacia schrieb:

    Das sollte davon nicht tangiert werden. In diesem Fall ist es ja kein Quick&Dirty-Fix, sondern die Komponente benutzt Strings anstelle von Byte-Arrays. Und da sind nunmal AnsiStrings richtig, da ihre Elementgröße 1 ist.

    Es müsste aber ein Quick&Dirty-Fix daraus gemacht werden um weiterhin Dateien zu öffnen die mit AnsiString Dateinamen gespeichert wurden und nun auch Unicode Dateinamen zulässig sein sollen.



  • Daß das Dateiformat beibehalten werden muß, sehe ich nicht als "quick&dirty" an. Und wenn du Unicode-Unterstützung willst, wäre es denkbar, das Dateiformat rückwärtskompatibel zu erweitern. Beispiel: wenn die Strings mit 0xEE 0xBB 0xBF beginnen, sind sie UTF-8-codiert.



  • Hallo zusammen

    @audacia

    Merke: zwischen Modulen, die mit verschiedenen Compilern oder auch nur abweichenden Compilerversionen erstellt wurden, nur über C-Interfaces kommunizieren. Das gilt für alle Arten der Module, also für Objektdateien (.obj) und Sammlungen derselben (.lib) gleichermaßen wie für DLLs.

    Wenn ich dies richtig verstehe, kann ich unter BCB6 eine lib erstellen welche intern den "alten" AnsiString verwendet, nur die Parameter sollten von AnsiString auf char* umgestellt werden.

    Das kompilieren unter CG2009 habe ich versucht, war jedoch nicht erfolgreich.

    Kurz zur Vorgeschichte/Erklärung:
    Ich habe als der BCB6 neu war ein Programm erstellt, welches einen MD5 Hash über Dateien rechnet und prüft (Hash wird anschließend in diese Datei geschrieben).
    Hierfür wurde damals der MD5Coder von Indy8 verwendet. Das der Md5Coder einen Bug hat und keinen "echten" MD5 Hash errechnet ist damals nicht aufgefallen, da der Hash mit der gleichen Komponente erstellt und geprüft wurde.
    Mit Indy9 kam dann die Ernüchterung und es wurde klar, daß Indy8 hier einen Bug hat. Also lib mit Indy8 erstellt und zukünftig diese immer als Workaround verwendet.
    Das das komplette Programm nun auf CG2009 umgestellt werden soll, habe ich nun das Problem, daß ich den Indy8 Md5Coder irgendwie mit CG2009 zum laufen bekommen muß.

    Unter BCB6 lässt sich alles kompilieren, jedoch beim CG2009 bekomme ich nun diese Fehler:

    [DCC Warnung] iduri_V8.pas(58): W1050 WideChar in Set-Ausdrücken auf ByteChar verkürzt.  Ziehen Sie die Verwendung der Funktion 'CharInSet' aus der Unit 'SysUtils' in Betracht.
    [DCC Warnung] idglobal_V8.pas(616): W1050 WideChar in Set-Ausdrücken auf ByteChar verkürzt.  Ziehen Sie die Verwendung der Funktion 'CharInSet' aus der Unit 'SysUtils' in Betracht.
    [DCC Warnung] idglobal_V8.pas(764): W1050 WideChar in Set-Ausdrücken auf ByteChar verkürzt.  Ziehen Sie die Verwendung der Funktion 'CharInSet' aus der Unit 'SysUtils' in Betracht.
    [DCC Warnung] idglobal_V8.pas(988): W1058 Implizite String-Umwandlung mit potenziellem Datenverlust von 'string' zu 'ShortString'
    [DCC Warnung] idglobal_V8.pas(991): W1057 Implizite String-Umwandlung von 'ShortString' zu 'string'
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::~TCustomOutline()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::TCustomOutline(Classes::TComponent *)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::SetOutlineStyle(Outline::TOutlineStyle)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::SetOutlineOptions(System::Set<Outline::TOutlineOption, 0, 2>)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::GetPicture(int)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::SetPicture(int, Graphics::TBitmap *)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TOutlineNode::GetFullPath()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TOutlineNode::HasChildren()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TOutlineNode::getFirstChild()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TOutlineNode::GetNextChild(int)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::Insert(int, const System::UnicodeString)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TOutlineNode::GetLastChild()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::Add(int, const System::UnicodeString)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::AddChild(int, const System::UnicodeString)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::Get(int)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::Clear()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TOutlineNode::SetExpandedState(bool)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::SetSelectedItem(int)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::Click()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::GetSelectedItem()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::Expand(int)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::Loaded()' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes 'Outline::TCustomOutline::' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::DefineProperties(Classes::TFiler *)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::DrawCell(int, int, const Types::TRect&, System::Set<Grids::Grids__3, 0, 2>)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__tpdsc__ Outline::TCustomOutline' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::SetItemHeight(int)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::StoreBitmap(int)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    [ILINK32 Fehler] Error: Nicht auflösbares externes '__fastcall Outline::TCustomOutline::SetStyle(Outline::TOutlineType)' referenziert von D:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\BCBSMP.LIB|cdiroutl.cpp
    

    Das komplette kompilieren unter CG2009 wäre mir auch am liebsten.
    Irgendwelche Anregungen?

    MfG Stephan



  • Hallo zusammen

    Also nach etwas auprobieren kann ich nun die ganze Sache kompilieren.
    Das Projekt (Fehler von vorherigem Post) war eine DLL und nachdem ich daraus eine Exe gemacht habe hat's funktioniert. Siehe auch http://www.marquardtnet.info/cecke/quickies.1/1_quicky_43.html Lösung 3.

    Allerdings stimmt nun die Berechnung des MD5 Hash aus Indy8 nicht mehr.
    Kann mir eventuell jemand etwas zu den Warnings sagen, habe von Delphi leider keine Ahnung.

    [DCC Warnung] iduri_V8.pas(58): W1050 WideChar in Set-Ausdrücken auf ByteChar verkürzt.  Ziehen Sie die Verwendung der Funktion 'CharInSet' aus der Unit 'SysUtils' in Betracht.
    
    class procedure TIdURI.NormalizePath(var APath: string);
    var
      i: Integer;
    begin
      i := 1;
      while i <= Length(APath) do
      begin
        if APath[i] in LeadBytes then  //Zeile 58
        begin
          inc(i, 2)
        end
        else
          if APath[i] = '\' then
        begin
          APath[i] := '/';
          inc(i, 1);
        end
        else
        begin
          inc(i, 1);
        end;
      end;
    end;
    
    [DCC Warnung] idglobal_V8.pas(988): W1058 Implizite String-Umwandlung mit potenziellem Datenverlust von 'string' zu 'ShortString'
    
    function URLDecode(psSrc: string): string;
    var
      i: Integer;
      ESC: string[2];
      CharCode: integer;
    begin
      Result := ''; { do not localize }
      psSrc := StringReplace(psSrc, '+', ' ', [rfReplaceAll]); {do not localize}
      i := 1;
      while i <= Length(psSrc) do
      begin
        if psSrc[i] <> '%' then { do not localize }
        begin {do not localize}
          Result := Result + psSrc[i]
        end
        else
        begin
          Inc(i);
          ESC := Copy(psSrc, i, 2);  //Zeile 988
          Inc(i, 1);
          try
            CharCode := StrToInt('$' + ESC); {do not localize}
            if (CharCode > 0) and (CharCode < 256) then
              Result := Result + Char(CharCode);
          except
          end;
        end;
        Inc(i);
      end;
    end;
    
    [DCC Warnung] idglobal_V8.pas(991): W1057 Implizite String-Umwandlung von 'ShortString' zu 'string'
    
    function URLDecode(psSrc: string): string;
    var
      i: Integer;
      ESC: string[2];
      CharCode: integer;
    begin
      Result := ''; { do not localize }
      psSrc := StringReplace(psSrc, '+', ' ', [rfReplaceAll]); {do not localize}
      i := 1;
      while i <= Length(psSrc) do
      begin
        if psSrc[i] <> '%' then { do not localize }
        begin {do not localize}
          Result := Result + psSrc[i]
        end
        else
        begin
          Inc(i);
          ESC := Copy(psSrc, i, 2);
          Inc(i, 1);
          try
            CharCode := StrToInt('$' + ESC); {do not localize}  //Zeile 991
            if (CharCode > 0) and (CharCode < 256) then
              Result := Result + Char(CharCode);
          except
          end;
        end;
        Inc(i);
      end;
    end;
    

    Vielen Dank im voraus.
    MfG Stephan



  • Stephan schrieb:

    Wenn ich dies richtig verstehe, kann ich unter BCB6 eine lib erstellen welche intern den "alten" AnsiString verwendet, nur die Parameter sollten von AnsiString auf char* umgestellt werden.

    Ja.

    Stephan schrieb:

    Kann mir eventuell jemand etwas zu den Warnings sagen, habe von Delphi leider keine Ahnung.

    (Das würde ich dringend ändern. Delphi-Kenntnis ist für C++Builder-Programmierer von entscheidendem Vorteil.)

    Stephan schrieb:

    [DCC Warnung] iduri_V8.pas(58): W1050 WideChar in Set-Ausdrücken auf ByteChar verkürzt.  Ziehen Sie die Verwendung der Funktion 'CharInSet' aus der Unit 'SysUtils' in Betracht.
    

    Was ein Set ist, dürfte dir aus C++Builder bekannt sein. In Delphi ist das ein intrinsischer Typ, z.B.:

    type
      TOrdinal = (One, Two, Three);
      TOrdinals = set of TOrdinal;
    
    const
      SomeOrdinals: TOrdinals = [One, Three];
    

    Aber auch:

    type
      TSysCharSet = set of AnsiChar;
    
    const
      AlphaNumericChars: TSysCharSet = ['A'..'Z', 'a'..'z', '0'..'9', '_'];
      WhitespaceChars = [' ', #09];
    

    Wie im letzten Beispiel ersichtlich, kann die explizite Typangabe auch weggelassen werden; der Compiler deduziert den Typen dann anhand der Elementtypen.

    Hier liegt nun das Problem: seit Delphi 2009 sind Char-Literale wie ' ' und #09 nicht mehr AnsiChars, sondern WideChars. Nun enthält ein Set für jeden möglichen Wert des darunterliegenden Typen ein Flag-Bit. TOrdinals benötigt also drei Bits, TSysCharSet 256 Bits = 32 Bytes. Ein WideChar-Set jedoch wären 65536 Bits = 8 KB groß, und da das in den meisten Fällen unerwünscht ist, konvertiert der Delphi-Compiler diese Sets unter besagter Warnung zu AnsiChar-Sets.

    Stephan schrieb:

    [DCC Warnung] idglobal_V8.pas(988): W1058 Implizite String-Umwandlung mit potenziellem Datenverlust von 'string' zu 'ShortString'
    

    [...]

    [DCC Warnung] idglobal_V8.pas(991): W1057 Implizite String-Umwandlung von 'ShortString' zu 'string'
    

    String[n] entspricht SmallString<n> und ist ein auf n AnsiChars begrenzter String. Die anderen Strings, die du benutzt, basieren nun aber auf WideChar, weshalb implizite Konvertierungen stattfinden.

    Die URLDecode()-Funktion unterstützt allerdings Unicode-Codierungen nicht richtig; du könntest einfach die entsprechende Funktion aus Indy 10 ausleihen:

    // IdURI.pas, l. 302ff:
    class function TIdURI.URLDecode(ASrc: string): string;
    var
      i: Integer;
      ESC: string;
      CharCode: Integer;
    begin
      Result := '';    {Do not Localize}
      // S.G. 27/11/2002: Spaces is NOT to be encoded as "+".
      // S.G. 27/11/2002: "+" is a field separator in query parameter, space is...
      // S.G. 27/11/2002: well, a space
      // ASrc := StringReplace(ASrc, '+', ' ', [rfReplaceAll]);  {do not localize}
      i := 1;
      while i <= Length(ASrc) do begin
        if ASrc[i] <> '%' then begin  {do not localize}
          Result := Result + ASrc[i]; // Copy the char
          Inc(i); // Then skip it
        end else begin
          Inc(i); // skip the % char
          if not CharIsInSet(ASrc, i, 'uU') then begin  {do not localize}
            // simple ESC char
            ESC := Copy(ASrc, i, 2); // Copy the escape code
            Inc(i, 2); // Then skip it.
            try
              CharCode := IndyStrToInt('$' + ESC);  {do not localize}
              Result := Result + Char(CharCode);
            except end;
          end else
          begin
            // unicode ESC code
    
            // RLebeau 5/10/2006: under Win32, the character will end
            // up as '?' in the Result when converted from Unicode to Ansi,
            // but at least the URL will be parsed properly
    
            ESC := Copy(ASrc, i+1, 4); // Copy the escape code
            Inc(i, 5); // Then skip it.
            try
              CharCode := IndyStrToInt('$' + ESC);  {do not localize}
              Result := Result + {$IFDEF UNICODESTRING}Char{$ELSE}WideChar{$ENDIF}(CharCode);
            except end;
          end;
        end;
      end;
    end;
    

Anmelden zum Antworten