SendMessage i przesyłanie wskaźnika na TList<MyRecord>

0

Szukam w google i znalazłem ale nie dokońca to o co mi chodziło. Nie zamierzam kopiować całej listy rekordów a jedynie odczytać już istniejące. Zmienna string wiem jak przesłać ale z klasą mam problem.

type
  Rekord = record
     tekst: string;
     liczba: integer;
  end;

  Watek = class(TThread)
  public
     procedure Execute;
  end;  

procedure TWatek.Execute;
var
     List: TList<Rekord>;
     s: string;
     r: Rekord;
begin
    List := TList<Rekord>.Create;
    r.Text := 'Fajnie';
    r.Liczba := 5;
    List.Add(r);  
    s := 'To działa';
    SendMessage(Handle, WM, integer(@s), LP_EndGetList);  //Czekaj na obsłużenie
    SendMessage(Handle, WM, integer(@List), LP_EndGetList);  //Czekaj na obsłużenie
    List.Free;
end;

procedure  Odebrano(var Msg: TMessage);
var
   tekst: string;
   PList: ^TList<Rekord>;
   List: TList<Rekord>; 
begin
   tekst := PString(Msg.LParam)^;    //Tutaj zmienna tekst zawiera prawidłowy string
   List :=   PList(Msg.LParam)^;  // To się nie kompiluje  Missing operator or semicolon
end; 
  
1
Ania2020 napisał(a):

Szukam w google i znalazłem ale nie dokońca to o co mi chodziło. Nie zamierzam kopiować całej listy rekordów a jedynie odczytać już istniejące. Zmienna string wiem jak przesłać ale z klasą mam problem.

No może.
Tylko cały ten kod jest niepotrzebny, ponieważ:

var
  lList : TList<Rekord>;
  lInt  : integer;
begin
  lList : TList<Rekord>.Create;
  try
    lInt := Integer(lList);
    lList := TList<Rekord>(lInt);
  finally
    lList
  end;
end;

A poza tym, coś to śliskie się wydaje...
Na pewno nie chcesz wykorzystać synchronizacji zamiast wysyłki komunikatów bez synchronizacji?

0
wloochacz napisał(a):
Ania2020 napisał(a):

Szukam w google i znalazłem ale nie dokońca to o co mi chodziło. Nie zamierzam kopiować całej listy rekordów a jedynie odczytać już istniejące. Zmienna string wiem jak przesłać ale z klasą mam problem.

No może.
Tylko cały ten kod jest niepotrzebny, ponieważ:

var
  lList : TList<Rekord>;
  lInt  : integer;
begin
  lList : TList<Rekord>.Create;
  try
    lInt := Integer(lList);
    lList := TList<Rekord>(lInt);
  finally
    lList
  end;
end;

A poza tym, coś to śliskie się wydaje...
Na pewno nie chcesz wykorzystać synchronizacji zamiast wysyłki komunikatów bez synchronizacji?

Tak to próbowałam na samym początku ale to mimo iż się kompiluje to nie działa wcale. Ponieważ zamiast

lInt := Integer(lList); musi być** lInt := Integer(@lList);** wtedy uzyskujemy poprawny adres w pamięci.

Natomiast to uzyskuje wartość inaccessible value
** lList := TList<Rekord>(lInt); **

Jeżeli to powyżej by działało to o ile się nie mylę to wykonanie poniższego kodu powinno dać wynik: adres1 = adres2 ale tak nie jest


var
  lList : TList<Rekord>;
  IList2: TList<Rekord>;
  R: Rekord;
  addres1,addres2  : integer;
begin
   lList := TList<Rekord>.Create;
   R.Tekst := 'Test';
   IList.Add(R);
   
   addres1 := Integer(@lList);
   lList2 := TList<Rekord>(addres1);
   addres2 := Integer(@lList2);
 end;
0
Ania2020 napisał(a):
wloochacz napisał(a):
Ania2020 napisał(a):

Szukam w google i znalazłem ale nie dokońca to o co mi chodziło. Nie zamierzam kopiować całej listy rekordów a jedynie odczytać już istniejące. Zmienna string wiem jak przesłać ale z klasą mam problem.

No może.
Tylko cały ten kod jest niepotrzebny, ponieważ:

var
  lList : TList<Rekord>;
  lInt  : integer;
begin
  lList : TList<Rekord>.Create;
  try
    lInt := Integer(lList);
    lList := TList<Rekord>(lInt);
  finally
    lList
  end;
end;

A poza tym, coś to śliskie się wydaje...
Na pewno nie chcesz wykorzystać synchronizacji zamiast wysyłki komunikatów bez synchronizacji?

Tak to próbowałam na samym początku ale to mimo iż się kompiluje to nie działa wcale.

Oczywiście że działa i działa poprawnie.

Ponieważ zamiast

lInt := Integer(lList); musi być** lInt := Integer(@lList);** wtedy uzyskujemy poprawny adres w pamięci.

Yhy, doczytaj sobie jeszcze o wskaźnikach w Delphi...
Ponieważ nie potrzebujesz adresu zmiennej tylko wartości z tego adresu zmiennej, bo tam jest przechowana referencja na obiekt.
Jak tak będziesz robić, to wcale nie dziwne że nie działa.

Natomiast to uzyskuje wartość inaccessible value

Zatem ustaw sobie poprawnie opcje kompilacji.

** lList := TList<Rekord>(lInt); **

Jeżeli to powyżej by działało to o ile się nie mylę to wykonanie poniższego kodu powinno dać wynik: adres1 = adres2 ale tak nie jest

Oczywiście, że się mylisz.
Sprawdź taki kod:

type
  TRekord = record
    txt : string;
  end;

var
  lList  : TList<TRekord>;
  lList2 : TList<TRekord>;
  R      : TRekord;
  lAddr1 : NativeInt;
  lAddr2 : NativeInt;
begin
   lList := TList<TRekord>.Create;
   try
     R.txt := 'Test';
     lList.Add(R);

     // poprawne rzutowanie refrenecji obiektu na integer
     lAddr1 := Integer(lList);

     //To nie jest rzutowanie referencji na int, tylko wartość adresu w pamięci dla tej referencji
     lAddr2 := Integer(@lList);

     // poprawna referencja na TList<TRekord>
     lList2 := TList<TRekord>(lAddr1);

     // a tu będą śmieci i każde dotknięcie obiektu lList2 skończy się AV
     lList2 := TList<TRekord>(lAddr2);
   finally
     lList.Free;
   end;
end;

0

W końcu jest sukces, przestudiowałam artykuł o wskaźnikach z tej strony i poniżej działający kod, teraz go tylko dobrze po testować :)

type
   TRecord = TList<TRekord>;
   PRecord = ^TRecord;

var 
  List_Send: TList<TRekord>;
  List_Back: TList<TRekord>;
  PList: PRecord;
  Adres: integer;
begin
 List_Send := TList<TRekord>.Create;
 Adres := Integer(@List_Send);
 //........................
 PList := PRecord(Adres);
 PList^.Items[0].JakaśZmienna 
end;
0
Ania2020 napisał(a):

W końcu jest sukces, przestudiowałam artykuł o wskaźnikach z tej strony i poniżej działający kod, teraz go tylko dobrze po testować :)

Super, tylko że (powtarzam się po raz ostatni) to niepotrzebne.

0
wloochacz napisał(a):
Ania2020 napisał(a):

W końcu jest sukces, przestudiowałam artykuł o wskaźnikach z tej strony i poniżej działający kod, teraz go tylko dobrze po testować :)

Super, tylko że (powtarzam się po raz ostatni) to niepotrzebne.

W twoim kodzie po tej instrukcji dodaj jeszcze taką:

 // poprawna referencja na TList<TRekord>
 lList2 := TList<TRekord>(lAddr1);
Showmessage(IList2[0].txt);

I wywala błąd AV a w drugim przypadku Argument out of range

0
wloochacz napisał(a):
Ania2020 napisał(a):

W końcu jest sukces, przestudiowałam artykuł o wskaźnikach z tej strony i poniżej działający kod, teraz go tylko dobrze po testować :)

Super, tylko że (powtarzam się po raz ostatni) to niepotrzebne.

Kod który podałeś działa w aplikacji 32 bitowej ale w 64 bitach zobacz co się dzieje.

title

0
Ania2020 napisał(a):
wloochacz napisał(a):
Ania2020 napisał(a):

W końcu jest sukces, przestudiowałam artykuł o wskaźnikach z tej strony i poniżej działający kod, teraz go tylko dobrze po testować :)

Super, tylko że (powtarzam się po raz ostatni) to niepotrzebne.

Kod który podałeś działa w aplikacji 32 bitowej ale w 64 bitach zobacz co się dzieje.

Weź przestań kompulsywnie walić w klawiaturę tylko się zastanów dlaczego nie działa?
Dlaczego zmieniłem Integer na NativeInt? Nic nie świata?
I dlaczego ty twardo w kodzie trzymasz się rzutowania na Integer z adresu który jest Int64 w kompilacji x64?
I właśnie dlatego działa na x86, ale nie działa na x64.

Teraz jasne, dlaczego się wywala?

Zmień wszystkie wystąpienie Integer na NativeInt.

PS.
@furious programming teraz już rozumiesz po co jest NativeInt? :D

0
wloochacz napisał(a):

PS.
@furious programming teraz już rozumiesz po co jest NativeInt? :D

Ja to wiedziałem już wtedy, gdy kłóciliśmy się w komentarzach. Tylko wtedy uznałeś, że wspomniane przeze mnie „wyraźne potrzeby” nie dotyczą rzutowania pointerów. Sam korzystam, ale z PtrUInt, bo jest on naturalny dla FPC, a NativeInt oraz NativeUInt zostały wprowadzone dla kompatybilności z Delphi.

W ramach ciekawostki dodam, że we Free Pascalu NativeInt to alias PtrInt, a wrowadzenie typu PtrInt jest uznawane przez deweloperów kompilatora za ”błąd” i zalecają używanie PtrUInt – co zresztą jest logiczne, bo adres nie może być ujemny, więc po co obcinać zakres? Nawet pomimo tego, że w wielu miejscach biblioteki standardowej i komponentów wykorzystywany jest wariant ze znakiem. ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1