Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Pointer & Co (https://www.delphipraxis.net/148518-pointer-co.html)

gibb 3. Mär 2010 13:14


Pointer & Co
 
Hi,

Ich versuche zur zeit gerade das hier:
http://hobbyelektronik.org/VB/SF/SpeedFan.htm

nach zu bauen...

Leider stell ich mich ziemlich doof an... mir fehlt einfach die Erfahrung mit dem Arbeiten mit den Pointer/Buffer. In Delphi kann man sich ja davor ziemlich gut drücken :oops:

Tja, jetzt wüsste ich halt gerne wie ich das unten zum laufen kriege... resp. wie ich den text auslesen kann. Hab jetzt etliches über pointer gelsen aber wirklich verstanden hab ichs leider nicht und hoffe jetzt das ihr mir helfen könntet.

Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
  hSFMemory: hwnd ;
  SfAreaPtr: Pointer;
  MyResultPtr: Pointer;
begin
Try
   GetMem(MyResultPtr,1000);
   hSFMemory:= openfilemapping(FILE_MAP_READ,false,'SFSharedMemory_ALM');
   if HSFMemory <> 0 then begin
     SfAreaPtr := MapViewOfFile(hSFMemory, FILE_MAP_READ, 0, 0, 0);
     CopyMemory(MyResultPtr,SfAreaPtr, 1000);
     memo1.Text:= AnsiString(PChar(MyResultPtr));

   end;

  Finally
    FreeMem(MyResultPtr);
   // FreeMem(SfAreaPtr);
    UnmapViewOfFile(SfAreaPtr);
    CloseHandle(hSFMemory);
  End;
end;
Gruss Gibb

himitsu 3. Mär 2010 14:07

Re: Pointer & Co
 
Erstmal würde ich es in eine eigene Unite verlegen,
dann sollte dich Delphi über die eventuell uninitialisierten Variablen verwarnt haben.

Delphi-Quellcode:
function GetSFString: String;
var
  hSFMemory: HWND;
  SfAreaPtr: PAnsiChar;
begin
  hSFMemory := 0;
  SfAreaPtr := nil;
  try
    hSFMemory := OpenFileMapping(FILE_MAP_READ, False, 'SFSharedMemory_ALM');
    if HSFMemory <> 0 then begin
      SfAreaPtr := MapViewOfFile(hSFMemory, FILE_MAP_READ, 0, 0, 0);
      Result := SfAreaPtr;
    end else
      Result := '';
  finally
    UnmapViewOfFile(SfAreaPtr);
    CloseHandle(hSFMemory);
  end;
end;
Außerdem willst du den Speicherbereich als Text auslesen, was wohl (laut dem Beispiel) nicht stimmt,
schau dir das Beispiel nochmal genau an, such den Record (also den Aufbau der Daten in diesem Speicherbereich) raus und greife über diesen Record auf die Daten zu.


Delphi-Quellcode:
function GetSFString: ...;
var
  hSFMemory: HWND;
  SfAreaPtr: PSFRawMemMap;
begin
  hSFMemory := 0;
  SfAreaPtr := nil;
  try
    hSFMemory := OpenFileMapping(FILE_MAP_READ, False, 'SFSharedMemory_ALM');
    if HSFMemory <> 0 then begin
      SfAreaPtr := MapViewOfFile(hSFMemory, FILE_MAP_READ, 0, 0, 0);
      ... // SfAreaPtr^.irgendwas
    end else
      ...;
  finally
    UnmapViewOfFile(SfAreaPtr);
    CloseHandle(hSFMemory);
  end;
end;
[add]
@p80286: jupp, hab ich ... zumindestens etwas genauer überflogen :angel:

p80286 3. Mär 2010 14:12

Re: Pointer & Co
 
Hallo gibb

so könnte es funktionieren:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  hSFMemory: hwnd ;
  SfAreaPtr: Pointer;
  MyResultPtr: Pointer;
  Bufferstr : string;
begin
  setlength(bufferstr,1000);
Try
   MyResultPtr:=@bufferstr[1];
   hSFMemory:= openfilemapping(FILE_MAP_READ,false,'SFSharedMemory_ALM');
   if HSFMemory <> 0 then begin
     MyResultPtr := MapViewOfFile(hSFMemory, FILE_MAP_READ, 0, 0, 0);
     //CopyMemory(MyResultPtr,SfAreaPtr, 1000);
     memo1.Text:= bufferstr;

   end;

  Finally
  //  FreeMem(MyResultPtr);
   // FreeMem(SfAreaPtr);
    UnmapViewOfFile(myResultPtr);
    CloseHandle(hSFMemory);
  End;
end;

end.
und wo liegen die Probleme bei Buffern und Pointern?
Ein Buffer ist ein Speicherbereich (Array, String ....) in den man Daten Schreibenkann und ein Pointer ist eine Adresse (diese Bereiches)
z.B.
Delphi-Quellcode:
var
  Buffer : array [0..1023] of byte;
  BuffPtr : pointer;
begin
....
  BuffPtr:=@Buffer[0];
....
 
end;
Gruß
K-H

Edit: Da hat wohl jmd. das Beispiel besser gelesen als ich!

gibb 3. Mär 2010 14:50

Re: Pointer & Co
 
Hi und danke für die Antworten.

Also ich kenne den Record nicht unter VB daher nehm ich an das es sich darum handelt, leider scheine ich da auch nicht mit auf einen grünen Zweig zu kommen :-(

Da es sich noch um ein test programm handelt mache ich mir noch keine weiteren Units.

Delphi-Quellcode:
   
unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
   PSFRawMemMap = Record
   public
     Unknown: Integer; //'unbekanntes Tag
     NumTemps:Integer; //'Anzahl der Temperaturen
     NumFans: Integer; //'Anzahl der Lüfter
     NumVolts: Integer;// 'Anzahl der Spannungen
     Temps: Integer; //'Werte der Temperaturen
     Fans: Integer; //'Drehzahl der Lüfter
     Volts: Integer; //'Werte der Spannungen'
   end;


  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
    procedure GetTemps();
    function FindWindowEx2(hParent: HWND; ChildClassName: string; ChildNr: Word): HWND ;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  GetTemps();
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  hSFMemory: HWND;
  SfAreaPtr: Pointer ;
  MyResultRecord: PSFRawMemMap;
begin
  hSFMemory := 0;
  SfAreaPtr := nil;
  try
    hSFMemory := OpenFileMapping(FILE_MAP_READ, False, 'SFSharedMemory_ALM');
    if HSFMemory <> 0 then begin
      SfAreaPtr := MapViewOfFile(hSFMemory, FILE_MAP_READ, 0, 0, 0);
      CopyMemory(Addr(MyResultRecord),SfAreaPtr,1000);
      memo1.Text := IntToStr(MyResultRecord.Fans);
    end;
  finally
    UnmapViewOfFile(SfAreaPtr);
    CloseHandle(hSFMemory);
  end;
end;

function TForm1.FindWindowEx2(hParent: HWND; ChildClassName: string; ChildNr: Word): HWND;
var
  i: Word;
  hChild: HWND;
begin
  hChild := 0;
  Result := 0;
  Dec(ChildNr);
  for i := 0 to ChildNr do
  begin
    hChild := FindWindowEx(hParent, hChild, PChar(ChildClassName), nil);
    if hChild = 0 then
      Break;
    Result := hChild;
  end;
end;

procedure TForm1.GetTemps();
var
  wndMain, wndChild: HWND;
  Text: PAnsiChar;
  MaxLength: Integer;

begin
  wndMain := FindWindow('TForm1','SpeedFan 4.40');
  if wndMain <> 0 then
  begin
    wndChild := FindWindowEx(wndMain, 0, 'TPageControl', nil);
    wndChild := FindWindowEx(wndChild, 0, 'TTabSheet', nil);
    wndChild := FindWindowEx2(wndChild,'TJvPanel', 3);
    MaxLength:= 1000;
    getWindowText(wndMain,Text,MaxLength);
    Memo1.Text:=Text;
  end;
end;


end.
Tja das klapt so jedenfalls auch nicht.

Das Zweite beispiel gibt auch nur KrimsKrams aus was aber anhand der ersten aussage kein Wunder ist ;)

Danke jedenfalls euch beiden ;)

Gruss Gibb

gibb 3. Mär 2010 16:35

Re: Pointer & Co
 
Wie finde ich anhand eines Pointers die speicherlänge auf die der Pointer verweisst heraus?

Gruss Gibb

p80286 3. Mär 2010 17:27

Re: Pointer & Co
 
Zitat:

Zitat von gibb
Wie finde ich anhand eines Pointers die speicherlänge auf die der Pointer verweisst heraus?

Gruss Gibb

garnicht!

woher weißt Du wie groß das Haus in 10034 Berlin, Bundesallee 12 ist?
einPointer ist nur eine Adresse, zunächst einmal. es gibt auch typisierte Pointer, also Zeiger die auf Strukturen zeigen, und da bemißt sich die Größe nach der zu Grunde liegenden Struktur.

Ich bin mir da nicht sicher aber das "MapViewOfFile(hSFMemory, FILE_MAP_READ, 0, 0, 0);" liefert doch nur garnichts (Daten) zurück!? Dann würde es mich auch nicht wundern wenn da nichts vernünftiges kommt.
Zitat:

LPVOID MapViewOfFile(

HANDLE hFileMappingObject, // file-mapping object to map into address space
DWORD dwDesiredAccess, // access mode
DWORD dwFileOffsetHigh, // high-order 32 bits of file offset
DWORD dwFileOffsetLow, // low-order 32 bits of file offset
DWORD dwNumberOfBytesToMap // number of bytes to map
Gruß
K-H

gibb 3. Mär 2010 19:59

Re: Pointer & Co
 
Naja ich schon nicht.. aber das Bauamt würde es sicher wissen. Aber wenn das nicht möglich ist frage ich mich wie das überhaupt funktionieren soll. Anhand deines vorherigen Beitrages bin ich davon ausgegangen das der Buffer das Haus währe der Pointer die adresse folglich müsste xy wissen wie gross der buffer ist wo die adresse hinzeigt.

Naja laut dem VB Code währe das ja so:
MyAreaPtr = MapViewOfFile(MyAreaH, FILE_MAP_READ, 0, 0, 0) 'Pointer herausfinden
CopyMemory VarPtr(mMyArea), MyAreaPtr, Len(mMyArea) 'und lesen!

also der CopyMemory befehl sollte mir die daten in mMyArea kopieren. So versteh ich das zumindest. Ebenso in Delphi. nur dann hab ich die daten bei der adresse abgelegt weiss aber immer noch nicht wie drauf zuzugreifen.

Gruss Gibb

gibb 4. Mär 2010 08:33

Re: Pointer & Co
 
Niemand mehr der mir sagen kann wie ich das angehen muss? Ich nehme schwer an das ich das mit dem Record auch falsch mache :-/

Ich habe leider echt keine ahnung wie das funktioniert :-(

Der Herr der den VB Code geschrieben hat konnte ja sein Record irgendwie anpassen, ich nehme an das zeigt an wieviele daten wo zu gehören.. wie geht das denn in delphi? mir währ nichts solches bekannt. Ein Integer holt sich ja immer gleichviel speicher :-/

p80286 4. Mär 2010 10:00

Re: Pointer & Co
 
Hallo Gibb,
nun mal langsam. Ich würde es so machen:
erst einmal als Buffer ein Array of byte. Den dann Byte für Byte anschauen was wirklich rüber kommt, und dann ein record drüber legen.
Delphi-Quellcode:
const
  mbuff :=32
type
  tmyrecord : packed record
                feld1 : integer;
                feld2 : integer;
              ....
             end;
var
  buffer : array [0..mbuff];
  myrecord : tmyrecord absolute buffer;
Gruß
K-H

edit: mbuff natürlich so groß wählen, das auf jeden Fall genug platz ist!
und natürlich vor dem Lesen mit fillchar nullen!

gibb 4. Mär 2010 12:04

Re: Pointer & Co
 
Juhuu erste erfolge stellen sich ein :D

Folgender Code:

Delphi-Quellcode:
unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;



type
  { PSFRawMemMap = Record
   public
     Unknown: Integer; //'unbekanntes Tag
     NumTemps:Integer; //'Anzahl der Temperaturen
     NumFans: Integer; //'Anzahl der Lüfter
     NumVolts: Integer;// 'Anzahl der Spannungen
     Temps: Integer; //'Werte der Temperaturen
     Fans: Integer; //'Drehzahl der Lüfter
     Volts: Integer; //'Werte der Spannungen'
   end;                }


  TMyRecord = packed record
  public
     Unknown: Integer; //'unbekanntes Tag
     NumTemps:Integer; //'Anzahl der Temperaturen
     NumFans: Integer; //'Anzahl der Lüfter
     NumVolts: Integer;// 'Anzahl der Spannungen
     Temps: Integer; //'Werte der Temperaturen
     Fans: Integer; //'Drehzahl der Lüfter
     Volts: Integer; //'Werte der Spannungen'
   end;


  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
  public
    { Public declarations }
  end;

const
  mbuff = 100;

var
  Form1: TForm1;
  buffer : array [0..mbuff] of integer;
  myrecord : tmyrecord absolute buffer;

implementation

{$R *.dfm}


procedure TForm1.Button2Click(Sender: TObject);
var
  hSFMemory: HWND;
  SfAreaPtr: Pointer ;
  MyResultRecord: TMyRecord;
  i: Integer;
  txt: String;
begin
  fillchar(buffer,1000,0);
  hSFMemory := 0;
  SfAreaPtr := nil;
  i := 0;
  try
    hSFMemory := OpenFileMapping(FILE_MAP_READ, False, 'SFSharedMemory_ALM');
    if HSFMemory <> 0 then begin
      SfAreaPtr := MapViewOfFile(hSFMemory, FILE_MAP_READ, 0, 0, 0);
      CopyMemory(Addr(buffer),SfAreaPtr,1000);
      while i < 99 do begin
        Text:= inttostr(buffer[i]);
        memo1.Text := memo1.Text + text+ #13+ #10; // IntToStr(MyResultRecord.Fans);
        inc(i);
      end;
    end;
  finally
    UnmapViewOfFile(SfAreaPtr);
    CloseHandle(hSFMemory);
  end;
end;
end.
Liefert mir das hier zurück
Zitat:

65537
402
198236
3
255590400
183500800
176947200
0
0
0....0
Jetzt blick ich nur noch nicht durch wie ich was mit diesen Zahlen anfangen kann =D Aber immerhin kommen bereits Zahlen.

gruss Sev

gibb 4. Mär 2010 13:41

Re: Pointer & Co
 
Hi,

hab jetzt folgendes gemacht:
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
  hSFMemory: HWND;
  SfAreaPtr: Pointer ;
  MyResultRecord: TMyRecord;
  i: Integer;
  txt: String;
begin
  fillchar(buffer,1000,0);
  hSFMemory := 0;
  SfAreaPtr := nil;
  i := 0;
  try
    hSFMemory := OpenFileMapping(FILE_MAP_READ, False, 'SFSharedMemory_ALM');
    if HSFMemory <> 0 then begin
      SfAreaPtr := MapViewOfFile(hSFMemory, FILE_MAP_READ, 0, 0, 0);
      CopyMemory(Addr(buffer),SfAreaPtr,1000);
      MyResultRecord.Unknown:= buffer[0];
      MyResultRecord.NumTemps:= buffer[1];
      MyResultRecord.NumFans:= buffer[2];
      MyResultRecord.NumVolts:= buffer[3];
      MyResultRecord.Temps:= buffer[4];
      MyResultRecord.Fans:= buffer[5];
      MyResultRecord.Volts:= buffer[6];
    end;
  finally
    UnmapViewOfFile(SfAreaPtr);
    CloseHandle(hSFMemory);
  end;
end;
Wobei das scheint nicht zu stimmen, die einzige zahl die ich wiedererkenne währ numoftemps wobei diese so bei numofvolts eingetragen ist.

Was macht dieser VB Code? oder was ist der gedanke dabei?:
Zitat:

RetVal.Temps = mMyArea.NumTemps
RetVal.Volts = mMyArea.NumVolts
RetVal.Fans = mMyArea.NumFans
For x = 0 To 32 Step 2
RetVal.Temp(x / 2) = mMyArea.Temps(x) / 100
RetVal.Fan(x / 2) = mMyArea.Fans(x)
RetVal.Volt(x / 2) = mMyArea.Volts(x) / 100
Next
gruss gibb

guinnes 4. Mär 2010 13:56

Re: Pointer & Co
 
Dein Record stimmt doch noch gar nicht :
Delphi-Quellcode:
Private Type SF_Raw_MemMap
   Unknown(5) As Integer 'unbekanntes Tag
   NumTemps As Integer 'Anzahl der Temperaturen
   NumFans As Integer 'Anzahl der Lüfter
   NumVolts As Integer 'Anzahl der Spannungen
   Temps(63) As Integer 'Werte der Temperaturen
   Fans(63) As Integer 'Drehzahl der Lüfter
   Volts(63) As Integer 'Werte der Spannungen
End Type
Probier mal so
Delphi-Quellcode:
TSF_Raw_MemMap = Packet Record
   Unknown : Array[0..5] of Integer //unbekanntes Tag
   NumTemps : Integer //Anzahl der Temperaturen
   NumFans : Integer //Anzahl der Lüfter
   NumVolts : Integer //Anzahl der Spannungen
   Temps   : Array[0..63] of Integer //Werte der Temperaturen
   Fans    : Array[0..63] of Integer //Drehzahl der Lüfter
   Volts   : Array[0..63] of Integer //Werte der Spannungen
end;

gibb 4. Mär 2010 14:01

Re: Pointer & Co
 
Ah das is ein array in VB wenn eine klammer mit zahl angegeben wird..... dachte mir schon das die Zahlen für was sind, hab aber nicht geschnallt wofür. Hab das ja ettliche beiträge vorher schonmal geschrieben. Dank dir =D

guinnes 4. Mär 2010 14:05

Re: Pointer & Co
 
Die Array-Grenzen stimmen noch nicht :oops:
(5) ist 0..4 bzw 63 ist 0..62 laut http://www.vbarchiv.net/faq/strings_array.php
Edit : Da sind sich die Leute nicht einig : http://de.wikibooks.org/wiki/Visual_Basic_6:_Arrays
Nach dem lesen der beiden Seiten : Die Arraygrenzen stimmen doch, die Zahl in der Klammer gibt den höchsten Index an und der Startindex ist normalerweise 0 wenn kein Option Base 1 angegeben ist

gibb 4. Mär 2010 14:20

Re: Pointer & Co
 
Naja, hilft aber auch nicht weiter wenn da nicht mehr daten stehen oder?

http://www.abload.de/thumb/inspectorecos.jpg

PS: ich hab den buffer rausgeschmissen und versucht die daten gleich in den Record zu schreiben:
CopyMemory(Addr(MyResultRecord),SfAreaPtr,1000);

Sollte so doch auch stimmen, gibt mir ja die selben werte zurück nur bereits in die record struktur angepasst was meiner meinung nach ja unser ziel ist oder?

guinnes 4. Mär 2010 15:15

Re: Pointer & Co
 
fillchar(buffer,1000,0); // Dein Buffer ist gar nicht so groß

RetVal.Temps = mMyArea.NumTemps
RetVal.Volts = mMyArea.NumVolts
RetVal.Fans = mMyArea.NumFans
For x = 0 To 32 Step 2
RetVal.Temp(x / 2) = mMyArea.Temps(x) / 100
RetVal.Fan(x / 2) = mMyArea.Fans(x)
RetVal.Volt(x / 2) = mMyArea.Volts(x) / 100
Next

ist eine VB -Schleife, die die Integer aus den einzelnen Feldern in Floats umrechnet, wobei die Schrittweite 2 ist, also nur 16 Werte übertägt

gibb 4. Mär 2010 15:53

Re: Pointer & Co
 
Ist ein buffer immer wie ein Array aufgebaut?

Trozdem kommt nicht mehr als das hier:
http://www.abload.de/thumb/buffer156t.jpg

oberes bild ist mit:
Delphi-Quellcode:
CopyMemory(Addr(Buffer),SfAreaPtr,1000);
aber direkt so scheint auch zu gehen:
Delphi-Quellcode:
CopyMemory(Addr(MyResultRecord),SfAreaPtr,1000);
)

Was das erste bild zustande bringt, da hab ich den Buffer garnicht erst verwedet. Aber irgendwie scheine ich nicht alle daten zu kriegen ??

PS: wie kann ich z.b. die lenge von myResultRecord herausfinden? denn dann währe folgendes möglich:
Delphi-Quellcode:
CopyMemory(Addr(MyResultRecord),SfAreaPtr,length(MyResultRecord));
Ich gehe ja davon aus das der record der form der Daten die ich zurückbekomme entsprechen sollte...

p80286 4. Mär 2010 16:00

Re: Pointer & Co
 
Hallo Gibb,

im Prinzip liegst Du schon richtig aber
1)Dein MyresultRecord muß ein packed record sein
2) statt Length solltest du Sizeof verwenden, das gibt Dir die Größe in Bytes zurück.

z.B.
Delphi-Quellcode:
  a1 : array [0..3] of integer;

length(a1) >> 4  { 4 Integer}
sizeof(A1) >> 16 {16 Bytes }
Gruß
K-H

Edit: Tippfehler

gibb 4. Mär 2010 16:12

Re: Pointer & Co
 
1: isses doch:
Delphi-Quellcode:
  TMyRecord = packed record
  public
   Unknown : Array[0..5] of Integer; //unbekanntes Tag
   NumTemps : Integer; //Anzahl der Temperaturen
   NumFans : Integer; //Anzahl der Lüfter
   NumVolts : Integer; //Anzahl der Spannungen
   Temps   : Array[0..63] of Integer; //Werte der Temperaturen
   Fans    : Array[0..63] of Integer; //Drehzahl der Lüfter
   Volts   : Array[0..63] of Integer; //Werte der Spannungen
  end;
Also scheint beim Copy was nicht ganz zu stimmen :-( oder sonstwo

2: danke das hab ich gesucht XD wusste nur nicht wie die funktion heisst ^-^' war mir schon klar das length nicht geht, aber du hast es verstanden ;)

EDIT:

Habs jetzt so:
Delphi-Quellcode:
CopyMemory(Addr(MyResultRecord),SfAreaPtr,sizeof(MyResultRecord));
EDIT2:
Was könnt hier nicht stimmen?

Delphi-Quellcode:
    hSFMemory := OpenFileMapping(FILE_MAP_READ, False, 'SFSharedMemory_ALM');
    if HSFMemory <> 0 then begin
      SfAreaPtr := MapViewOfFile(hSFMemory, FILE_MAP_READ, 0, 0, 0);
      CopyMemory(Addr(MyResultRecord),SfAreaPtr,sizeof(MyResultRecord));
Das stimmt schon mit Addr von MyResultRecord oder?

CopyMemory nimmt ja nur Pointers folglich geb ich ihm den Pointer zu meinem Record. :-/

p80286 4. Mär 2010 16:49

Re: Pointer & Co
 
Also ich seh da jetzt keine Fehler, aber wie wäre es zb mit so etwas
Delphi-Quellcode:
Type
  pMyrecord:=^TMyrecord;

....
 
  SfAreaPtr := MapViewOfFile(hSFMemory, FILE_MAP_READ, 0, 0, 0);
  pMyrecord:=SfAreaPtr;
  CopyMemory(Addr(MyResultRecord),SfAreaPtr,sizeof(MyResultRecord));
und dann schau Dir mal den Inhalt von pMyRecord^ und MyResultRecord an, da sollte eigentlich das gleiche stehen.

(ich hatte die Record Definition übersehen)

Gruß
K-H

gibb 5. Mär 2010 08:24

Re: Pointer & Co
 
Macht leider keinen Unterschied. :-( hab ich dann einfach die daten falsch strukturiert zurückgenommen?

Oder was muss ich Zaubern damit es stimmt ?

Was vielleicht interessant sein dürfte ist das ich weder die volt angaben hab oder die fan angaben hier auf der HP kiste.(das einzige was ich hab sind 3 temps) aber das sollte doch dennoch stimmen im memory... sonst würde doch speedfan selber auch nicht funktionieren.

Gruss Gibb

guinnes 5. Mär 2010 08:31

Re: Pointer & Co
 
Wenn du folgende Deklaration benutzt, kommt was plausibles raus :
Delphi-Quellcode:
TSF_Raw_MemMap = Packet Record
   Unknown : Array[0..5] of SmallInt//unbekanntes Tag
   NumTemps : SmallInt //Anzahl der Temperaturen
   NumFans : SmallInt //Anzahl der Lüfter
   NumVolts : SmallInt //Anzahl der Spannungen
   Temps   : Array[0..63] of Integer //Werte der Temperaturen
   Fans    : Array[0..63] of Integer //Drehzahl der Lüfter
   Volts   : Array[0..63] of Integer //Werte der Spannungen
end;
NumTemps : 3
NumFans : 0
NumVolts : 0
Temps[0] = 3300 ( / 100 = 33°)
Temps[1] = 2700 ( / 100 = 27°)
Temps[2] = 2600 ( / 100 = 26°)

Die Zahlen, die als Integer bei dir angezeigt werden als Hex :

01 00 01 00 92 01 00 00 5c 06 03 00 03 00 00 00 00 00
e4 0c 00 00 8c 0a 00 00 28 0A
Als SmallInt :
01 00 = 1
01 00 = 1
92 01 = 402
00 00 = 0
5c 06 = 1628
03 00 = 3
03 00 = 3
00 00 = 0
00 00 = 0

Rest als Integer :
e4 0c 00 00 = 3300
8c 0a 00 00 = 2700
28 0A 00 00 = 2600

Edit : Ich hab hier auch ne HP-Kiste stehen, die hat auch fast nix an Sensoren

Blup 5. Mär 2010 09:27

Re: Pointer & Co
 
Hier noch eine etwas ausführlichere Deklaration:
Delphi-Quellcode:
  TSharedMem = packed record
    Version : Word;          {2 Byte}
    Flags   : Word;          {2 Byte}
    MemSize : Integer;       {4 Byte}
    Handle  : THandle;       {4 Byte}
    NumTemps : Word;          {2 Byte}
    NumFans : Word;          {2 Byte}
    NumVolts : Word;          {2 Byte}
    Value   : array[0..0] of Integer;
  end;
Packet Record :wink:

Edit:
Ob tatsächlich statisch 64 oder 32 Einträge für Temps usw. vorgesehen sind oder die Anzahl der Werte dynamisch und die Zuordnung zu Temp, Fan und Volt sich entsprechend verschiebt, ist zumindest mir nicht klar.

gibb 5. Mär 2010 12:54

Re: Pointer & Co
 
Hallo zusammen,

Danke vielmals ich jetzt funktionierts, (ist noch nicht ganz ausgereift der Code, aber so funktionieren die Grundlegenden sachen... wollte diesen auch mit der öffentlichkeit teilen ;))

Delphi-Quellcode:
unit Main;

interface

uses
  Windows, SysUtils, Classes, Forms,
    Controls, StdCtrls;



type

  TMyRecord = Packed Record
   Unknown : Array[0..5] of SmallInt;//unbekanntes Tag
   NumTemps : SmallInt; //Anzahl der Temperaturen
   NumFans : SmallInt; //Anzahl der Lüfter
   NumVolts : SmallInt; //Anzahl der Spannungen
   Temps   : Array[0..63] of Integer; //Werte der Temperaturen
   Fans    : Array[0..63] of Integer; //Drehzahl der Lüfter
   Volts   : Array[0..63] of Integer; //Werte der Spannungen
end;



  TForm1 = class(TForm)
    Memo1: TMemo;
    Button2: TButton;

    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }

  public
    { Public declarations }
  end;

const
  mbuff = 1000;

var
  Form1: TForm1;
  buffer : array [0..mbuff] of integer;
  myrecord : tmyrecord absolute buffer;

implementation

{$R *.dfm}



procedure TForm1.Button2Click(Sender: TObject);
var
  hSFMemory: HWND;
  SfAreaPtr: Pointer ;
  MyResultRecord: TMyRecord;
  i: Integer;
begin
  fillchar(buffer,1000,0);
  hSFMemory := 0;
  SfAreaPtr := nil;
  try
    hSFMemory := OpenFileMapping(FILE_MAP_READ, False, 'SFSharedMemory_ALM');
    if HSFMemory <> 0 then begin
      SfAreaPtr := MapViewOfFile(hSFMemory, FILE_MAP_READ, 0, 0, 0);
      CopyMemory(Addr(MyResultRecord),SfAreaPtr,sizeof(MyResultRecord));
      memo1.Text:= memo1.Text+'Number Of Temps:'+inttostr(MyResultRecord.NumTemps)+#13+#10;
      memo1.Text:= memo1.Text+'Number Of Fans:'+inttostr(MyResultRecord.NumFans)+#13+#10;
      memo1.Text:= memo1.Text+'Number Of Volts:'+inttostr(MyResultRecord.NumVolts)+#13+#10;
      For i:= 0 to MyResultRecord.NumFans -1 do begin
        MyResultRecord.Fans[i]:= MyResultRecord.Fans[i]div 100;
        memo1.Text:= memo1.Text+'Fan'+inttostr(i)+':'+inttostr(MyResultRecord.Fans[i])+#13+#10;
      end;
      For i:= 0 to MyResultRecord.numTemps -1 do begin
        MyResultRecord.Temps[i]:= MyResultRecord.Temps[i]div 100;
        memo1.Text:= memo1.Text+'Temp'+inttostr(i)+':'+inttostr(MyResultRecord.Temps[i])+#13+#10;
      end;

      For i:= 0 to MyResultRecord.NumVolts -1 do  begin
        MyResultRecord.Volts[i]:= MyResultRecord.Volts[i]div 100;
        memo1.Text:= memo1.Text+'Fan'+inttostr(i)+':'+inttostr(MyResultRecord.Volts[i])+#13+#10;
      end
    end;
  finally
    UnmapViewOfFile(SfAreaPtr);
    CloseHandle(hSFMemory);
  end;
end;

end.
Gruss Gibb

PS: Ja ich weiss sollte nicht mit div arbeiten ;) aber war gerade zu faul das alles vom int umzuwandeln.

gibb 8. Mär 2010 12:10

Re: Pointer & Co
 
hallo Zusammen,

Ich hab jetzt das hier in eine eigene unit ausgelagert:
Delphi-Quellcode:
unit ReadSpeedfanData;

interface
uses
  Windows,
  SysUtils,
  Classes,
  Forms,
  Controls,
  StdCtrls,
  Dialogs,
  messages;


type

  TResultIntRecord = Packed Record
    Unknown : Array[0..5] of SmallInt;//unbekanntes Tag
    NumTemps : SmallInt; //Anzahl der Temperaturen
    NumFans : SmallInt; //Anzahl der Lüfter
    NumVolts : SmallInt; //Anzahl der Spannungen
    Temps   : Array[0..63] of Integer; //Werte der Temperaturen
    Fans    : Array[0..63] of Integer; //Drehzahl der Lüfter
    Volts   : Array[0..63] of Integer; //Werte der Spannungen
  end;

  TResultStrRecord = Record
    NumTemps : SmallInt; //Anzahl der Temperaturen
    NumFans : SmallInt; //Anzahl der Lüfter
    NumVolts : SmallInt; //Anzahl der Spannungen
    Temps   : TStringList; //Werte der Temperaturen
    Fans    : TStringList; //Drehzahl der Lüfter
    Volts   : TStringList; //Werte der Spannungen
  End;

  TReadSpeedfan = Class(TObject)
  Private
    FIntData : TResultIntRecord;
    FstrData: TResultStrRecord;
    Function UpdateData: Boolean;
  Public
    Function ReadSFData: Boolean;
    Function GetstrResult: TResultStrRecord;

  End;


implementation



Function TReadSpeedfan.ReadSFData: Boolean;
var
  hSFMemory: HWND;
  SfAreaPtr: Pointer ;
  MyResultRecord: TResultIntRecord;
begin
  hSFMemory := 0;
  SfAreaPtr := nil;
  try
    hSFMemory := OpenFileMapping(FILE_MAP_READ, False, 'SFSharedMemory_ALM');
    if HSFMemory <> 0 then begin
      SfAreaPtr := MapViewOfFile(hSFMemory, FILE_MAP_READ, 0, 0, 0);
      CopyMemory(Addr(MyResultRecord),SfAreaPtr,sizeof(MyResultRecord));
      FintData:= MyResultRecord;
      Result:= True;
      If UpdateData = False then Result:= False;
    end else begin
      Result := False;
    end;
  finally
    UnmapViewOfFile(SfAreaPtr);
    CloseHandle(hSFMemory);
  end;
end;

Function TReadSpeedFan.UpdateData: Boolean;
var
  i: Integer;
  Temp : Single;
  PiAsStr: String;
Begin
  Try
    If not Assigned(FstrData.Temps) then
      FstrData.Temps:= TStringlist.Create;
    If not Assigned(FstrData.Fans) then
      FstrData.Fans:= TStringlist.Create;
    If not Assigned(FstrData.Volts) then
      FstrData.Volts:= TStringlist.Create;

    FstrData.Temps.Clear;
    FstrData.Fans.Clear;
    FstrData.Volts.Clear;

    For i:= 0 to FIntData.NumFans -1 do begin
      FstrData.Fans.Add('Fan'+inttostr(i)+':'+IntTostr(FIntData.Fans[i]));
    end;
    For i:= 0 to FIntData.NumTemps -1 do begin
      FstrData.Fans.Add('Temp'+inttostr(i)+':'+FormatFloat('###,##', fintData.Temps[i]/100));
    end;
    For i:= 0 to FIntData.NumVolts -1 do begin
      FstrData.Fans.Add('Voltage'+inttostr(i)+':'+FormatFloat('###,##', fintData.Temps[i]/100));
    end;

    FstrData.NumTemps:= FIntData.NumTemps;
    FstrData.NumFans:= FIntData.NumFans;
    FstrData.NumVolts:= FIntData.NumVolts;

    Result:= True;
  except
    Result:= False;
  End;
End;

Function TReadSpeedfan.GetstrResult (): TResultStrRecord;
var
  MyResultRecord: TResultStrRecord;
  i: Integer;
begin
  Result := FstrData;
end;

end.

Und ruffe es aus dem Main auf:
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
  SpeedFanReader : TReadSpeedfan;
begin
  SpeedFanReader.Create;

  Speedfanreader.ReadSFData;

  SpeedFanReader.free;

 sleep(1);

end;
Sobald er aber die Funktion abschliessen möchte kommen exceptions. Ich nehme an das es irgendwie an dem Copymemory befehl und nicht freigegeben speicehr resp. bereits freigegeben Speicher liegt. Hat da jemand ne ahnung was genau das problem ist?

Gruss Sev

gibb 8. Mär 2010 12:28

Re: Pointer & Co
 
Ach du meine güte -.- mann sollte wissen wie man ein objekt erzeugt -.-'

Sorry, Lösung fürs problem (und ich hab ca ne stunde dafür verbraten -.-):
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
  SpeedFanReader : TReadSpeedfan;
begin
  SpeedFanReader:= TReadSpeedfan.create;    //SpeedFanReader.Create; <- alt war so -.-

  Speedfanreader.ReadSFData;

  SpeedFanReader.free;

sleep(1);

end;

gibb 11. Mär 2010 16:53

Re: Pointer & Co
 
hi,
irgendwas stimmt da noch nicht :-( Laut VB code werden die Return werte durch 100 geteilt bis auf die fans. Das hier sind jetzt die werte die ich kriege ohne zu teilen (bis auf die temps natürlich die sind bereits durch 100 )
http://www.abload.de/image.php?img=s...reader30v8.png
stimmt in diesem fall etwas am array nicht? Komisch ist auch das er mir sagt er hätte 9 numofvolts aber danach doch nur 6 werte dafür hat.


Gruss Sev

gibb 12. Mär 2010 11:11

Re: Pointer & Co
 
niemand eine Idee? Lese ich die werte falsch aus? Stimmt der datentyp nicht? beim vb code versteh ich auch nicht wieso der ein Step2 drinnen hat. Bei mir kommt schön brav immer eine Zahl nach der anderen, wenn ich nen step 2 reintun würde würde ich die hälfte der werten verlieren.

Gruss Sev

guinnes 12. Mär 2010 11:34

Re: Pointer & Co
 
Delphi-Quellcode:
CopyMemory(Addr(MyResultRecord),SfAreaPtr,sizeof(MyResultRecord));
FintData:= MyResultRecord;
Result:= True;
Warum nicht :
Delphi-Quellcode:
CopyMemory(Addr(FintData),SfAreaPtr,sizeof(MyResultRecord));
Result:= True;
Delphi-Quellcode:
If UpdateData = False then Result:= False;
Boolsche Werte nie auf True oder False abfragen : http://www.delphi-treff.de/tutorials...oolean-werten/
Besser :
Delphi-Quellcode:
If Not UpdateData then Result:= False;
bzw an der Stelle kannst du gleich schreiben
Delphi-Quellcode:
Result := UpdateData

gibb 12. Mär 2010 11:59

Re: Pointer & Co
 
was mich sowieso auf einen Fehler gebracht hat ;)

Delphi-Quellcode:
Function TReadSpeedfan.ReadSFData: Boolean;
var
  hSFMemory: HWND;
  SfAreaPtr: Pointer ;
  MyResultRecord: TResultIntRecord;
begin
  result:= False;
  hSFMemory := 0;
  SfAreaPtr := nil;
  try
    hSFMemory := OpenFileMapping(FILE_MAP_READ, False, 'SFSharedMemory_ALM');
    if HSFMemory <> 0 then begin
      SfAreaPtr := MapViewOfFile(hSFMemory, FILE_MAP_READ, 0, 0, 0);
      CopyMemory(Addr(FintData),SfAreaPtr,sizeof(MyResultRecord));
      result:= UpdateData;
    end;
  finally
    UnmapViewOfFile(SfAreaPtr);
    CloseHandle(hSFMemory);
  end;
end;
was aber schlussendlich dasselbe resultat zurückliefert ;)

EDIT:

Wieso die Volts nicht stimmen konnten lag daran:
Delphi-Quellcode:
    For i:= 0 to FIntData.NumVolts -1 do begin
      FstrData.Volts.Add('Voltage'+inttostr(i)+':'+FormatFloat('###,##', fintData.Volts[i]/100));
    end;
hatte da FormatFloat('###,##', fintData.Temp[i]/100)

gibb 13. Mär 2010 00:04

Re: Pointer & Co
 
hi

Hab jetzt ne 30 Tage trial auf nem Rechner installiert um zu kapieren wo meine Daten hingehen. Ein Blick auf die Daten im Record erklärt wo sie sind ;)

http://www.abload.de/thumb/resultsnc5q.png

also, ich mir gedacht ich immitier euch und spiel einwenig mit den datentypen und habe aus den array of int ein array of smallint gemacht und kriege das hier:

Delphi-Quellcode:
  TResultIntRecord = Packed Record
    Unknown : Array[0..5] of SmallInt;//unbekanntes Tag
    NumTemps : SmallInt; //Anzahl der Temperaturen
    NumFans : SmallInt; //Anzahl der Lüfter
    NumVolts : SmallInt; //Anzahl der Spannungen
    Temps   : Array[0..63] of smallint; //Werte der Temperaturen
    Fans    : Array[0..63] of smallint; //Drehzahl der Lüfter
    Volts   : Array[0..63] of smallint; //Werte der Spannungen
  end;
http://www.abload.de/thumb/resultskzn9.png

Jetzt zwei fragen 1. wieso verhält es sich so ? Ich hab schon geschnallt das es mit der speichergrösse zusammenhängt mit welcher sich der datentyp sich reserviert. und folglich verschieben sich die Zahlen. Gibts noch mehr das man dazu wissen sollte? wie z.b. wie finde ich heraus welcher datentyp der richtige ist ohne lang drum herum zu probieren? oder sonstige theorie... ich würde mich da gerne noch einwenig vertiefen.

Frage2: Wieso lässt er immer noch ne 0 zwischen den einträgen? Wofür ist diese da?

Gruss GIBB

Blup 16. Mär 2010 14:55

Re: Pointer & Co
 
Mit SpeedFan 4.40 funktioniert bei mir diese Struktur (bzw. stimmt mit der Anzeige in SpeedFan überein):
Delphi-Quellcode:
  TSharedMem = packed record
    Version : Word;                   // 2 Byte
    Flags   : Word;                   // 2 Byte
    MemSize : Integer;                // 4 Byte
    Handle  : THandle;                // 4 Byte
    NumTemps : Word;                   // 2 Byte Anzahl der Temperaturen
    NumFans : Word;                   // 2 Byte Anzahl der Lüfter
    NumVolts : Word;                   // 2 Byte Anzahl der Spannungen
    Temps   : array[0..31] of Integer; // 32 * 4 Byte Werte der Temperaturen
    Fans    : array[0..31] of Integer; // 32 * 4 Byte Drehzahl der Lüfter
    Volts   : array[0..31] of Integer; // 32 * 4 Byte Werte der Spannungen
  end;
Es sind maximal 32 Werte je Typ.


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:41 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