Von Lazarus 1.2.6 nach Lazarus 1.8.0

Von Lazarus 1.2.6 nach Lazarus 1.8.0

Beitragvon SchwabenTom » 15. Jan 2018, 21:19 Von Lazarus 1.2.6 nach Lazarus 1.8.0

Hallo,

ich habe ein Programm mit Lazarus 1.2.6 angefangen. Das wurde auch kompiliert und lief auch. Nach einer Pause wollte ich mich nun wieder an dieses Programm setzen. Habe Lazarus dabei auf die aktuelle Version 1.8.0 aktualisiert. Damit bekomme ich Compilerfehler. Habe aber keine Änderungen am Code gemacht. Einfach nur mit der neuen Lazarusversion kompiliert.

Windows 7, 64 bit
Lazarus 1.8.0 (für windows 64 bit)

Ich greife auf das WMI von Windows zu. Es sind OLEVariant etc. im Spiel. Einen Übergabeparamter mußte ich mit nil angeben. Dafür bekomme ich einen Compilerfehler, daß es Lazarus genauer haben mag - nicht Pointer, sondern LongWord.

Code: Alles auswählen
 
...
var WMIService   : OLEVariant;
    WbemObjectSet: OLEVariant;
    WbemObject   : Variant;
    oEnum        : IEnumVariant;
...
...
          WbemObjectSet := WMIService.ExecQuery('SELECT * FROM Msvm_VirtualSystemManagementService', 'WQL', WMI_WbemFlagForwardOnly);
          oEnum         := IUnknown(WbemObjectSet._NewEnum) as IEnumVariant;
          if oEnum.Next(1, WbemObject, nil) = 0 then     // <-- hier der Fehler, das nil will er nicht
...
 


oEnum ist ein IEnumVariant. Den dritten Übergabeparameter muß ich laut den Hilfetexten und Beispielcodes die ich fand mit nil übergeben. Das hat Lazarus in v 1.2.6 auch so compiliert. Das Kompilat lief fehlerfrei. Jetzt mit Lazarus v 1.8.0 erhalte ich den Compilerfehler

Error: Call by var for arg no. 3 has to match exactly: Got "Pointer" expected "LongWord"

Lösung ist klar :-) Ich werd ein LongWord übergeben müssen :-)

Meine Frage ist nur, was ist das LongWord von nil?

Caste ich direkt mit: LongWord(nil)?
Ist es 0?
Ist es -1?
Oder etwas anderes?

Danke und Grüße,
Tom
SchwabenTom
 
Beiträge: 49
Registriert: 4. Jan 2015, 21:34
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z) | 
CPU-Target: xxBit
Nach oben

Beitragvon Mathias » 15. Jan 2018, 22:22 Re: Von Lazarus 1.2.6 nach Lazarus 1.8.0

Es ist Nil ist gleich 0

Dieser kleiner Code bewies dies.
Code: Alles auswählen
var
  i:Integer;
begin
  i := 0;
  if nil = Pointer(i) then begin
    WriteLn('0 = nil');
  end;
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 4271
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon kupferstecher » 16. Jan 2018, 08:35 Re: Von Lazarus 1.2.6 nach Lazarus 1.8.0

SchwabenTom hat geschrieben:Caste ich direkt mit: LongWord(nil)?

Hallo Tom,
fuer pointer-gecaste gibt es PtrUInt, dann ist gewaehrleistet, dass die Bitbreite auch passt (32bit/64bit).
Obs hier in deinem speziellen Fall geht, musst du probieren.
Also ptruint(nil).
kupferstecher
 
Beiträge: 155
Registriert: 17. Nov 2016, 11:52

Beitragvon m.fuchs » 16. Jan 2018, 12:34 Re: Von Lazarus 1.2.6 nach Lazarus 1.8.0

Mathias hat geschrieben:Es ist Nil ist gleich 0

Das stimmt sicherlich in den meisten Fällen, es muss aber nicht so sein. Es kann ja irgendwann mal eine Plattform dazukommen, in der nil dann anders definiert wird.
Deswegen immer nil verwenden (wenn nötig per Cast) anstelle von 0.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
m.fuchs
 
Beiträge: 1963
Registriert: 22. Sep 2006, 18:32
Wohnort: Berlin
OS, Lazarus, FPC: Winux (L 1.8.4, FPC 3.0.4) | 
CPU-Target: x86, x64, arm
Nach oben

Beitragvon Soner » 16. Jan 2018, 13:44 Re: Von Lazarus 1.2.6 nach Lazarus 1.8.0

Für Variantentypen wie OLEVariant nimmt man für Nil NULL.
Soner
 
Beiträge: 411
Registriert: 26. Sep 2012, 23:07
Wohnort: Hamburg
OS, Lazarus, FPC: Win7Pro-32Bit, Immer letzte Lazarus Release mit SVN-Fixes | 
CPU-Target: 32Bit
Nach oben

Beitragvon Mathias » 16. Jan 2018, 17:49 Re: Von Lazarus 1.2.6 nach Lazarus 1.8.0

m.fuchs hat geschrieben:
Mathias hat geschrieben:Es ist Nil ist gleich 0

Das stimmt sicherlich in den meisten Fällen, es muss aber nicht so sein. Es kann ja irgendwann mal eine Plattform dazukommen, in der nil dann anders definiert wird.
Deswegen immer nil verwenden (wenn nötig per Cast) anstelle von 0.


Ich bin von dieser Fehlermeldung ausgegangen:
Code: Alles auswählen
Error: Call by var for arg no. 3 has to match exactly: Got "Pointer" expected "LongWord"

Aber Normalerweise verwende ich bei einem Null-Pointer schon nil, Pointer(0) macht auch gar keine Sinn.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 4271
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon SchwabenTom » 24. Jan 2018, 21:54 Re: Von Lazarus 1.2.6 nach Lazarus 1.8.0

Danke für die schnellen Antworten. Bin gerade bei der Arbeit etwas stärker eingespannt ... deshalb liegt die "Frage" zur Zeit ein wenig in Warteschleife ... sorry für meine späte Rückmeldung. Die Null-Geschichte habe ich mal weiterverfolgt. Und bin gestoßen auf:

Variants.Null
VarIsNull
VarNull

---

VarNull

VarNull scheint in der varianth.inc (Zeile 21) definiert zu sein als

varnull = 1

Also ungleich 0.

Außerdem bekomme ich damit den Compilerfehler: "Error: Can't take the address of constant expressions"

----

VarIsNull ist klar, daß es nicht zu verwenden ist :-)

----

Variants.Null

Hier bekomme ich den Compilerfehler: "Error: Variable identifier expected".

----

Wenn ich es mit einer Variablen versuche, bekomme ich: Got "Variant" expected "LongWord".

Code: Alles auswählen
 
...
myTestVar: Variant;
...
myTestVar := Variants.Null;
if oEnum.Next(1, WbemObject, myTestVar) = 0 then
 


Dabei habe ich mehrere Kombinationen versucht myTestVar als Variant, als OLEVariant. Und Zuweisung myTest := Variants.Null und := VarNull.
Immer die selber Compilermeldung: Got "Variant" expected "LongWord" bzw. Got "OleVariant" expected "LongWord"

Wenn ich dann das Ding als LongWord deklariere funktionierts -> myTestVar: LongWord;

Aber dann bringt er mir, daß der zweite Parameter falsch sei. Bei

if oEnum.Next(1, WbemObject, myTestVar) = 0 then

kommt der Compilerfehler: Error: Call by var for arg no. 2 has to match exactly: Got "Variant" expected "OleVariant"

Ist ja auch definiert als -> WbemObject : Variant;

Ok, also das geändert in OLEVariant und siehe da:


Code: Alles auswählen
 
...
var WMIService   : OLEVariant;
    WbemObjectSet: OLEVariant;
    WbemObject   : OLEVariant;     // <-- das ist geändert
    oEnum        : IEnumVariant;
    myTestVar      : LongWord;     // <-- das ist neu
...
...
          WbemObjectSet := WMIService.ExecQuery('SELECT * FROM Msvm_VirtualSystemManagementService', 'WQL', WMI_WbemFlagForwardOnly);
          oEnum         := IUnknown(WbemObjectSet._NewEnum) as IEnumVariant;
          myTestVar        := VarNull;     // <-- das ist neu
          if oEnum.Next(1, WbemObject, myTestVar) = 0 then     // <-- das ist geändert
...
 


So wird compiliert, keine Fehlermeldung.

Wie gesagt VarNull ist mit 1 in der varianth.inc definiert.

Übrigens: mit "myVarNull := Variants.Null" meckert der Compiler ebenfalls nicht. Kein Fehler, scheint OK.

Wenn ich Variants.Null versuche nachzuverfolgen, lande ich am Ende wieder bei VarNull. Dh. auch Variants.Null müßte also die 1 sein.

Wenn die beiden aber 1 sind. NIL aber scheints die 0 sein soll .... ???

Was übergebe ich jetzt an die Funtkion: 0 oder 1 ???

Grüße, Tom
SchwabenTom
 
Beiträge: 49
Registriert: 4. Jan 2015, 21:34
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z) | 
CPU-Target: xxBit
Nach oben

Beitragvon SchwabenTom » 24. Jan 2018, 22:28 Re: Von Lazarus 1.2.6 nach Lazarus 1.8.0

Nachtrag: Hat mir doch keine Ruhe gelassen. Ich dachte mir eben, daß das Problem wie üblich evtl. nicht im, sondern vorm Computer liegt (sitzt), respektive Monitor :-)

Habe also nochmal nach diesem Enum.Next gegoogelt und sofort ganz oben folgende gefunden:

1.

https://forum.lazarus.freepascal.org/in ... ic=30007.0

Der nutzt in seinem Code einmal

EnumVarinat.Next(1, WbemObject, Value)

und einmal auch das nil

EnumVarinat.Next(1, WbemObject, nil)

-> Aber was mir hier aufgefallen ist: das Value wird nicht initialisiert.

2.

http://borland.public.delphi.winapi.nar ... hods-topic

Der hat ein

while (Enum.Next(1, v, @fetched) = S_OK) do

und hat das fetched ebenfalls nicht initialisiert

3.

https://forum.lazarus.freepascal.org/in ... ic=30933.0

molly, reply #3 -> scheint mir der beste Code in diesem Zusammenhang zu sein.

while ( EnumVar.Next(1, WbemObject, NrRetValues) = 0 ) do

Hier wird NrRetValues ebenfalls nicht initialisiert. Der Name scheint anzudeuten: das ist ein Rückgabeparameter, kein Eingabeparameter.

4.

https://www.board4all.biz/threads/hdd-p ... er.610774/

Der Code sieht für mich ebenfalls sehr gut aus.

Auch hier wird iValue nicht initalisiert.


----

Conclusion

Ich hatte da wohl einen Denkfehler - oder habs falsch in der Doku gelesen, überlesen. Das ist kein Eingabeparameter. Ich kann da also keine Konstante übergeben.

Blöd, daß ich nun ein paar tausend Zeilen Code durchgehen muß, um zu sehen, wo ich sonst noch die MS-Doku falsch verstanden habe :-( Aber gut für andere, die das mit dem Enum.Next jetzt im Forum finden :-)



PS.: Wollen wir trotzdem noch die Frage klären, daß nil = 0 und NULL (mit Variants.Null und VarNull) = 1. Daß die also unterschiedlich sind. Müssen die unterschiedlich sein? Die Antwort könnte sicher interessant und auch für andere hilfreich sein.


Grüße, SchwabenTom
SchwabenTom
 
Beiträge: 49
Registriert: 4. Jan 2015, 21:34
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z) | 
CPU-Target: xxBit
Nach oben

Beitragvon marcov » 25. Jan 2018, 10:25 Re: Von Lazarus 1.2.6 nach Lazarus 1.8.0

Die Unterschied kommt von:

------------------------------------------------------------------------
r26863 | michael | 2014-02-24 10:56:24 +0100 (Mon, 24 Feb 2014) | 1 line

* Fix IENumVariant interface to be more delphi compatible
------------------------------------------------------------------------

Den letzten Parameter ist nun kein Pointer mehr, aber ein OUT x: ULONG :

Code: Alles auswählen
// alt:
     Function  Next(celt: ULONG; OUT rgVar: VARIANT;  pCeltFetched: pULONG=nil):HResult;StdCall;
// neu:
     Function  Next(celt: ULONG; OUT rgVar: OLEVARIANT;  out pCeltFetched: ULONG):HResult;StdCall;
 


Original war es ein eingabe Zeigertyp (mit dem Idee das Next dann der "fetched" Anzahl in pceltfetched^ zuruch gab). Jetzt handelt der Compiler das ab, OUT is wie VAR, aber ohne eingabe.
marcov
 
Beiträge: 1031
Registriert: 5. Aug 2008, 08:37
Wohnort: Eindhoven (Niederlande)
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk) | 
CPU-Target: 32/64,PPC(+64), ARM
Nach oben

• Themenende •

Zurück zu Windows



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste

porpoises-institution
accuracy-worried