[Gelöst] Casting TObject zu Integer funktioniert nicht.

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
kirchfritz
Beiträge: 169
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

[Gelöst] Casting TObject zu Integer funktioniert nicht.

Beitrag von kirchfritz »

Kann mir mal jemand erklären warum der Sourcecode meines Minimalprojects nicht mehr funktioniert:

Code: Alles auswählen

program Project1;
 
{$mode objfpc}{$H+}
 
uses
  Classes;
 
var
  sl : TStringList;
  i : integer;
 
begin
  sl := TStringList.create;
  with sl do
  begin
    Clear;
    AddObject('hello', TObject(1));
    AddObject('in', TObject(2));
    AddObject('there', TObject(3));
  end;
  for i := 0 to sl.Count - 1 do
  begin
    writeln(integer(sl.Objects[i]));
  end;
  sl.Free;
end.
 

Bei der Writeln Anweisung kommt als Fehlermeldung:

Code: Alles auswählen

Error illegal type conversion from TObject to LongInt


Das hat bei mir immer funktioniert, aber seit dem Umstieg auf Lazarus 1.8 und damit auf FPC 3.0.4 geht das irgendwie nicht mehr.
Hat irgendjemand eine Idee, was da bei mir falsch läuft?

Für Eure Hilfe wäre ich sehr dankbar.
Fritz
Zuletzt geändert von kirchfritz am Mo 5. Feb 2018, 09:46, insgesamt 1-mal geändert.


mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Casting TObject zu Integer funktioniert nicht. Warum?

Beitrag von mse »

kirchfritz hat geschrieben:Kann mir mal jemand erklären warum der Sourcecode meines Minimalprojects nicht mehr funktioniert:

Weil du vielleicht auf 64 bit gewechselt bist. pointer (64bit) ist nicht mehr mit integer(32bit) kompatibel.

Code: Alles auswählen

 
  for i := 0 to sl.Count - 1 do
  begin
   writeln(ptrint(sl.Objects[i]));
  end;
 

kirchfritz
Beiträge: 169
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

[Gelöst] Casting TObject zu Integer funktioniert nicht. Waru

Beitrag von kirchfritz »

Danke mse, Danke theo,

in leichter Abwandlung funktioniert 's jetzt

Code: Alles auswählen

program Project1;
 
{$mode objfpc}{$H+}
 
uses
  Classes;
 
var
  sl : TStringList;
  i : Qword;
begin
  sl := TStringList.create;
  with sl do
  begin
    Clear;
    i := 1;
    AddObject('hello', TObject(i));
    i := 2;
    AddObject('in', TObject(i));
    i := 3;
    AddObject('there', TObject(i));
  end;
  for i := 0 to sl.Count - 1 do
  begin
    writeln(PtrInt(sl.Objects[i]));
  end;
  sl.Free;
end.
 


Für alle, die diesen Beitrag später mal lesen sollten:
Wichtig ist, dass die Variable i vom Type QWord ist und die Writeln-Anweisung das Casting mit PtrInt macht.

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: [Gelöst] Casting TObject zu Integer funktioniert nicht.

Beitrag von theo »

@kirchfritz, mse: Warum nicht den von mir vorgeschlagenen PtrUInt?
Was soll ein vorzeichenbehafteter Typ bei einem Pointer?
Ptrint is considered harmfull and should almost never be used in actual code, because pointers are normally unsigned.

https://www.freepascal.org/docs-html/rt ... trint.html

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: [Gelöst] Casting TObject zu Integer funktioniert nicht.

Beitrag von m.fuchs »

Darf ich dir auch noch eine Variante zeigen, die ganz ohne missbräuchlichem Cast auskommt?

Code: Alles auswählen

program Project1;
{$MODE ObjFpc}
{$H+}
 
uses
  Classes, SysUtils, Fgl;
 
type
  TStringIntegerMap = specialize TFPGMap<String, Integer>;
 
var
  Map: TStringIntegerMap;
  i: Integer;
 
begin
  Map := TStringIntegerMap.Create;
  Map.Clear;
  Map.Add('hello', 1);
  Map.Add('in', 2);
  Map.Add('there', 3);
  for i := 0 to Map.Count - 1 do begin
    WriteLn(Map.Data[i]);
  end;
  FreeAndNil(Map);
end.     
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: [Gelöst] Casting TObject zu Integer funktioniert nicht.

Beitrag von Mathias »

Für was wird AddObjects gebraucht ?
Ist dies zum durchnummerieren der einzelnen Stringeinträge ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: [Gelöst] Casting TObject zu Integer funktioniert nicht.

Beitrag von mse »

theo hat geschrieben:@kirchfritz, mse: Warum nicht den von mir vorgeschlagenen PtrUInt?

Um eine integer in einem pointer zu speichern ist ptrint der geeignete Typ.
Um eine cardinal in einem pointer zu speichern ist ptruint der geeignete Typ.
Zuletzt geändert von mse am Di 6. Feb 2018, 11:17, insgesamt 1-mal geändert.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: [Gelöst] Casting TObject zu Integer funktioniert nicht.

Beitrag von af0815 »

mse hat geschrieben:Um eine integer in einem pointer zu speichern ist ptrint der geeignete Typ.
Um eine cardinal in einem pointer zu speichern ist ptuint der geeignete Typ.

Zu meinem Verständnis - müsste man genaugenommen nicht den Integer/Cardinal/... mit Boxing und Unboxing behandeln (=ein Objekt daraus machen) damit ist entsprechend sicher ist und auch auf den verschiedenen Plattformen arbeitet ist ?! Weil hier ist man ja ansonsten IMHO Plattformabhängig.


Andreas
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: [Gelöst] Casting TObject zu Integer funktioniert nicht.

Beitrag von mse »

Ich glaube nicht. Die Bit-Grössen von integer/cardinal sind immer <= Bit-Grösse von pointer.

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: [Gelöst] Casting TObject zu Integer funktioniert nicht.

Beitrag von kupferstecher »

theo hat geschrieben:@kirchfritz, mse: Warum nicht den von mir vorgeschlagenen PtrUInt?
Was soll ein vorzeichenbehafteter Typ bei einem Pointer?
Ptrint is considered harmfull and should almost never be used in actual code, because pointers are normally unsigned.


Zum Beispiel bei PostMessage wird als Argument für WParam und LParam ein PtrInt erwartet.
Was würde passieren, wenn man aber auf PtrUInt castet? Kompilieren tut es zumindest.
Und was kann passieren, wenn man auf Ptrint castet, in Fällen wo PtrUInt erwartet wird?

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: [Gelöst] Casting TObject zu Integer funktioniert nicht.

Beitrag von theo »

kupferstecher hat geschrieben:
theo hat geschrieben:@kirchfritz, mse: Warum nicht den von mir vorgeschlagenen PtrUInt?
Was soll ein vorzeichenbehafteter Typ bei einem Pointer?
Ptrint is considered harmfull and should almost never be used in actual code, because pointers are normally unsigned.


Zum Beispiel bei PostMessage wird als Argument für WParam und LParam ein PtrInt erwartet.
Was würde passieren, wenn man aber auf PtrUInt castet? Kompilieren tut es zumindest.
Und was kann passieren, wenn man auf Ptrint castet, in Fällen wo PtrUInt erwartet wird?


"Harmful" heißt in diesem Falle mMn nicht, dass etwas in die Hose gehen muss, aber du musst einfach ganz genau wissen was du tust. Wie bei Assembler o.ä.

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: [Gelöst] Casting TObject zu Integer funktioniert nicht.

Beitrag von kupferstecher »

Mir geht es darum, was überhaupt passieren kann.

Ich hab mir angeschaut, was herauskommt, wenn man eine uInt8 (Byte) mit dem Wert $FF auf Int8 castet, das Ergebnis ist -1. Soweit so klar, aber auch über eine Zuweisung kommt das gleiche Ergebnis raus. In die andere Richtung von Int8 auf uInt8 kommt wieder $FF heraus, sowohl beim casten als auch über eine Zuweisung. D.h. das Vorzeichen beschädigt nicht das Bitmuster. Für den Anwendungsfall dass eine Bibliothek einen Pointer per Integer oder Unsigned erwartet, wäre es also erstmal egal, ob man per ptrInt oder ptrUInt castet.

Dann gäbe es noch den Fall, dass man Adressen berechnen möchte (Arrays etc.). Aber auch dort wandelt man ja nach erfolgter Berechnung wieder in einen Pointer um, es ist also wieder nur das Bitmuster entscheidend.

Antworten