Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Error: Inkompatible Typen Reguläre Prozedur u Methodenzeiger (https://www.delphipraxis.net/98744-error-inkompatible-typen-regulaere-prozedur-u-methodenzeiger.html)

BlueStarHH 31. Aug 2007 15:12


Error: Inkompatible Typen Reguläre Prozedur u Methodenzeiger
 
Ich habe mir eine eigene Klasse von TList abgeleitet. Dieser möchte ich eine Sortierfunktion hinzufügen. Dazu muss man der vorhandenen TList-Funktion Sort etwas vom Typ TListSortCompare übergeben. Ich bekomme es nicht hin. An der markierten Stelle kommt die Fehlermeldung "Inkompatible Typen: Reguläre Prozedur und Methodenzeiger"

Delphi-Quellcode:
  TMyList = class(TList)
  private
     SortedColumn: Integer;
     function MyListSortCompare(Item1, Item2: Pointer): Integer;
  public
     procedure SortByColumn(Column: Integer);
  end;

procedure TMyList.SortByColumn(Column: Integer);
begin
  SortedColumn := Column;
  Sort(MyListSortCompare); //<-- FEHLER: Inkompatible Typen: Reguläre Prozedur und Methodenzeiger
end;

function TMyList.MyListSortCompare(Item1, Item2: Pointer): Integer;
begin
  result := MachWas(Item1, Item2, SortedColumn);
end;

mkinzler 31. Aug 2007 15:16

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
self.Sort()

BlueStarHH 31. Aug 2007 15:18

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Zitat:

Zitat von mkinzler
self.Sort()

Klappt damit nicht, da dies nicht das Problem ist. Meine neue Sort-Methode heißt SortByColum. Daher gibt es da keine Namenskollision.

Apollonius 31. Aug 2007 15:19

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
MyListSortCompare muss eine einfache Funktion sein, keine Methode. Deklariere sie also nicht in der Klasse und lasse das TMyList bei der Definition weg.

BlueStarHH 31. Aug 2007 15:22

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Zitat:

Zitat von Apollonius
MyListSortCompare muss eine einfache Funktion sein, keine Methode. Deklariere sie also nicht in der Klasse und lasse das TMyList bei der Definition weg.

Das geht nicht weil ich in MyListSortCompare zugriff auf die Instanzvaribale "SortedColumn" brauche! Wie könnte ich darauf zugrifen, wenn ich MyListSortCompare außerhab der Klasse deklariere?

sirius 31. Aug 2007 15:28

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Was sind denn deine Listenelemente?

BlueStarHH 31. Aug 2007 15:30

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Zitat:

Zitat von sirius
Was sind denn deine Listenelemente?

Selbst erstellte Klassen, abgeleitet von TObject. Meiner Einschätzung nach, sollten die für die Fragestellung jedoch nicht relevant sein.

Apollonius 31. Aug 2007 15:30

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
hier gibt es bei den Schweizern Code, um einen Methodenzeiger in einen Funktionszeiger zu konvertieren. Das wäre was du suchst, ABER: Diese Funktion erfordert stdcall, während deine Funktion Register sein muss. Kannst du Assembler (=und dir selbst eine derartige Funktion für register schreiben)? Sonst könnte ich das mal probieren...

BlueStarHH 31. Aug 2007 15:38

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Hi Apollonius,

Assembler kann ich leider gar nicht. Ich wäre Dir also sehr dankbar, wenn Du (oder andere) es mal probieren würden.

sirius 31. Aug 2007 15:40

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Es dürfte reichen deiner Methode ein stdcall anzuhängen.

Delphi-Quellcode:
TMyList = class(TList)
  private
     SortedColumn: Integer;
     function MyListSortCompare(Item1, Item2: Pointer): Integer; stdcall;
  public
     procedure SortByColumn(Column: Integer);
  end;

procedure TMyList.SortByColumn(Column: Integer);
var MyListComparef:function(Item1,Item2:Pointer):integer;
begin
  SortedColumn := Column;
  MyListcomparef:=MakeProcInstance(MyListcompare);
  Sort(MyListSortComparef); //<-- FEHLER: Inkompatible Typen: Reguläre Prozedur und Methodenzeiger
  FreeProcinstance(MyListcompareF);
end;

function TMyList.MyListSortCompare(Item1, Item2: Pointer): Integer;
begin
  result := MachWas(Item1, Item2, SortedColumn);
end;

BlueStarHH 31. Aug 2007 15:45

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Das klappt so leider auch nicht. Es kommt ein neuer Fehler:

Delphi-Quellcode:
TMyList = class(TList)
  private
     SortedColumn: Integer;
     function MyListSortCompare(Item1, Item2: Pointer): Integer; stdcall;
  public
     procedure SortByColumn(Column: Integer);
  end;

procedure TMyList.SortByColumn(Column: Integer);
var MyListComparef:function(Item1,Item2:Pointer):integer;
begin
  SortedColumn := Column;
  MyListcomparef:=MakeProcInstance(MyListSortCompare); //<-- Fehler: Nicht genügend wirkliche Parameter
  Sort(MyListSortCompare);
  FreeProcinstance(MyListcompareF);
end;

function TMyList.MyListSortCompare(Item1, Item2: Pointer): Integer;
begin
  result := MachWas(Item1, Item2, SortedColumn);
end;

shmia 31. Aug 2007 15:51

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Delphi-Quellcode:
TMyList = class(TList)
  protected
     SortedColumn: Integer;
  public
     procedure SortByColumn(Column: Integer);
  end;

implementation
var
   _sortlist: TMyList; // globale hilfsvariable

// "normale" Funktion
function MyListSortCompare(Item1, Item2: Pointer): Integer;
begin
  result := MachWas(Item1, Item2, _sortlist.SortedColumn);
end;

procedure TMyList.SortByColumn(Column: Integer);
begin
  SortedColumn := Column;
  _sortlist := self;
  Sort(MyListSortCompare);
end;

Muetze1 31. Aug 2007 15:52

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
... Oder einfach ein QuickSort selber implementieren...

sirius 31. Aug 2007 15:58

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
:gruebel: Das muss auch einfach ohne ASM gehen
Delphi-Quellcode:
procedure TMyList.SortByColumn(Column: Integer);
var MyListComparef:function(Item1,Item2:Pointer):integer;
    m:Tmethod;
begin
  SortedColumn := Column;

  asm //m.code:=@MyListCompare (ging leider nur so)
    push edi
    mov edi, offset MyListCompare
    mov m.code,edi
    pop edi
  end;

  m.Data:=self;

  MyListcomparef:=MakeProcInstance(m); //<-- Fehler: Nicht genügend wirkliche Parameter
  Sort(MyListSortCompare);
  FreeProcinstance(MyListcompareF);
end;
Wie weist man nur m eine Methode zu? :gruebel:

BlueStarHH 31. Aug 2007 16:01

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Zitat:

Zitat von Muetze1
... Oder einfach ein QuickSort selber implementieren...

Das könnte man natürlch machen. Aber es könnte ja auch mal andere Fälle geben, wo man es nicht mal eben selbst implementeiren könnte. Deswegen müsste es doch eine Lösung geben? Eine globale Hilfsvariable wie von shmia vorgeschalgen ist auch nicht das gelbe vom Ei. Da verstößt gegen jegliche Grundsätze vom OOP und bringt Probleme, wenn ich mehrere Instanzen geleichzeitig nutzen möchten (z.B. in Threads).

jbg 31. Aug 2007 16:16

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Zitat:

Zitat von sirius
Delphi-Quellcode:
  asm //m.code:=@MyListCompare (ging leider nur so)
    push edi
    mov edi, offset MyListCompare
    mov m.code,edi
    pop edi
  end;

Pfui.
Delphi-Quellcode:
m.Code := @TMyList.MyListCompare;
Und zum Code "der Schweizer" muss ich sagen: Viel glück unter Systemen mit aktivierter Data Execution Prevention (DEP).


Delphi-Quellcode:
type
  TSortCompareMethod = function(Item1, Item2: Pointer): Integer of object;

procedure MQuickSort(SortList: PPointerList; L, R: Integer;
  SCompare: TSortCompareMethod);
var
  I, J: Integer;
  P, T: Pointer;
begin
  repeat
    I := L;
    J := R;
    P := SortList^[(L + R) shr 1];
    repeat
      while SCompare(SortList^[I], P) < 0 do
        Inc(I);
      while SCompare(SortList^[J], P) > 0 do
        Dec(J);
      if I <= J then
      begin
        if I <> J then // kleine zusätzliche Optimierung
        begin
          T := SortList^[I];
          SortList^[I] := SortList^[J];
          SortList^[J] := T;
        end;
        Inc(I);
        Dec(J);
      end;
    until I > J;
    if L < J then
      MQuickSort(SortList, L, J, SCompare);
    L := I;
  until I >= R;
end;

procedure TMyList.Sort(Compare: TListSortCompareMethod);
begin
  if (FList <> nil) and (Count > 0) then
    MQuickSort(FList, 0, Count - 1, Compare);
end;

sirius 31. Aug 2007 16:20

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Zitat:

Pfui.
Delphi-Quellcode:
m.Code := @TMyList.MyListCompare;

Mir lags auf der Zunge :oops:
Ich habe heute auch einen schweren Tag hintermir.

Zitat:

Und zum Code "der Schweizer" muss ich sagen: Viel glück unter Systemen mit aktivierter Data Execution Prevention (DEP).
Das hatte ich woanders schonmal mit Luckie diskutiert/gelöst/geändert. :zwinker:


Edit: Ich sollte besser ins Bett

Apollonius 31. Aug 2007 16:23

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Fertig.
Delphi-Quellcode:
function MakeListSortMethodProc(Method:TListSortMethod): TListSortCompare;
begin
Pointer(result):=VirtualAlloc(0, $0F, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
asm
//mov ecx, edx
mov [eax],    $D189
//mov edx, eax
mov [eax+$02], $C289
//mov eax, Method.Data
mov [eax+$04], $B8
mov ecx, [ebp+$0C]
mov [eax+$05], ecx
//push Method.Code
mov [eax+$09], $68
mov ecx, [ebp+$08]
mov [eax+$0A], ecx
//ret
mov [eax+$0E], $C3
end;
end;

procedure FreeListSortProc(Proc: TListSortCompare);
begin
VirtualFree(Pointer(@Proc), 0, MEM_RELEASE);
end;
Ihr Assemblerkundigen da draußen, nehmt es mal kritisch unter die Lupe.

[Edit] Zusätzlich zu Sirius' Korrektur nocheinmal 6 Bytes Assemblercode gespart. [/edit]

sirius 31. Aug 2007 16:29

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Zitat:

Ihr Assemblerkundigen da draußen, nehmt es mal kritisch unter die Lupe.
Assembler ist das eine..fließend Intel x86 zu lesen (hatten wir gestern in nem anderen Thread) ist aber etwas anderes.

Also, vorausgesetzt, dein Kommentar passt zu den Opcodes, denn fehlt ein "$C3"=return am Ende.

Apollonius 31. Aug 2007 16:34

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Tja, sowas kommt davon, sich selbst zu hetzen :( Ist korrigiert.
[edit] Nachtrag zum Thema hetzen: Buchstabendreher kommen auch daher.[/edit]

Real_Thunder 26. Feb 2008 19:06

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Habe mir Diese Thema nun schon 9 mal durchgelsesen.. und steige da einfahc nicht hinter.. währe nett wenn es jemand noch mal füür dumme erklären würde....

An sich habe ich das selbe Problem....

allergings habe ich keinen plan wie die eizelneen sachen aber definiert werden müssen.

also ich möchte auch erreichen das die sortierfunktion in einer klasse ist, damit ich davon mehrere instanzen erzeugen kann...

bekomme ich diese fehlermeldung:
Delphi-Quellcode:
[DCC Fehler] ExtGrid.pas(253): E2009 Inkompatible Typen: 'Reguläre Prozedur und Methodenzeiger'
der Quelltext sieht folgenermaßenn aus:

Delphi-Quellcode:
Type TExtStrGrid=Class

  SortCol:integer;
  SortDir:integer;

  PicUp:TImage;
  PicDown:TImage;
  LastDummy:boolean;
  SRow:integer;
  mausdown:boolean;
  Function CompareStringGridRows(item1,item2: Pointer):integer;
  Procedure DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
  procedure MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  procedure SortGrid(thegrid: TStringGrid; const col: integer);

  Constructor Create;
  destructor Destroy;


end;

implementation

..
..
..

Function TExtStrGrid.CompareStringGridRows(item1,item2: Pointer):integer;
var c1,c2: ^char;
    n1,n2: integer;
begin
  c1 :=@TStrings(item1).Strings[sortcol][1];
  c2 :=@TStrings(item2).Strings[sortcol][1];
  while (c1^ <>#0) and (c2^ <>#0) do
  begin
    if ((c1^ in ['0'..'9']) and (c2^ in ['0'..'9'])) then
    begin
      n1 :=0;
      n2 :=0;
      while (c1^ in ['0'..'9']) do
      begin
..
..
..

procedure TextStrGrid.SortGrid(thegrid: TStringGrid; const col: integer);
var rows: TList;
    id,i,j: integer;
    tmp: TStrings;
    tmp_row:string;
begin
try
  rows :=TList.Create;
  rows.Capacity :=thegrid.RowCount-thegrid.fixedrows;
  for i:=theGrid.fixedrows to thegrid.RowCount -1 do
  begin
    tmp :=TStringList.Create;
    for j:=0 to thegrid.ColCount-1 do
      tmp.AddObject(thegrid.cells[j,i],thegrid.Objects[j,i]);
      thegrid.Rows[i].Clear;
      rows.Add(tmp);
    end;
    rows.Sort(CompareStringGridRows); // Hier die Fehlermeldung..
    for i:=thegrid.fixedrows to thegrid.RowCount -1 do begin

DeddyH 26. Feb 2008 19:09

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Delphi-Quellcode:
Function TExtStrGrid.CompareStringGridRows(item1,item2: Pointer):integer;
So ist das eine Methode von TExtStrGrid.
Delphi-Quellcode:
Function CompareStringGridRows(item1,item2: Pointer):integer; stdcall;
Und so ist das eine Funktion. Nun klarer?

Real_Thunder 26. Feb 2008 21:28

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Zitat:

Zitat von DeddyH
Delphi-Quellcode:
Function TExtStrGrid.CompareStringGridRows(item1,item2: Pointer):integer;
So ist das eine Methode von TExtStrGrid.
Delphi-Quellcode:
Function CompareStringGridRows(item1,item2: Pointer):integer; stdcall;
Und so ist das eine Funktion. Nun klarer?


Hilft mir nicht wirklick weiter...
wenn ich nur den Stdall hinter Setzte bekomme ich die Fehlermeldung:
Delphi-Quellcode:
[DCC Fehler] ExtGrid.pas(253): E2009 Inkompatible Typen: 'Unterschiede in der Aufrufkonvention'
Ich werde aus den Ganzen kram nicht schlau...

Wie binde ich den Assembler Code richitg ein ? ...
Im Moment komme ich mir richtig doof vor .....

DeddyH 27. Feb 2008 08:20

Re: Error: Inkompatible Typen Reguläre Prozedur u Methodenze
 
Delphi-Quellcode:
Type TExtStrGrid=Class

  SortCol:integer;
  SortDir:integer;

  PicUp:TImage;
  PicDown:TImage;
  LastDummy:boolean;
  SRow:integer;
  mausdown:boolean;
//  Function CompareStringGridRows(item1,item2: Pointer):integer;
  Procedure DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
  procedure MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  procedure SortGrid(thegrid: TStringGrid; const col: integer);

  Constructor Create;
  destructor Destroy;


end;

implementation

..
..
..

Function {TExtStrGrid.}CompareStringGridRows(item1,item2: Pointer):integer;
var c1,c2: ^char;
    n1,n2: integer;
begin
  c1 :=@TStrings(item1).Strings[sortcol][1];
  c2 :=@TStrings(item2).Strings[sortcol][1];
  while (c1^ <>#0) and (c2^ <>#0) do
  begin
    if ((c1^ in ['0'..'9']) and (c2^ in ['0'..'9'])) then
    begin
      n1 :=0;
      n2 :=0;
      while (c1^ in ['0'..'9']) do
      begin
..
..
..

procedure TextStrGrid.SortGrid(thegrid: TStringGrid; const col: integer);
var rows: TList;
    id,i,j: integer;
    tmp: TStrings;
    tmp_row:string;
begin
try
  rows :=TList.Create;
  rows.Capacity :=thegrid.RowCount-thegrid.fixedrows;
  for i:=theGrid.fixedrows to thegrid.RowCount -1 do
  begin
    tmp :=TStringList.Create;
    for j:=0 to thegrid.ColCount-1 do
      tmp.AddObject(thegrid.cells[j,i],thegrid.Objects[j,i]);
      thegrid.Rows[i].Clear;
      rows.Add(tmp);
    end;
    rows.Sort(@CompareStringGridRows); // Hier die Fehlermeldung..
    for i:=thegrid.fixedrows to thegrid.RowCount -1 do begin
Versuch es mal so.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:16 Uhr.

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