John Gambler 0 Posted December 4 I'm having some difficulty using variables through their memory addresses. In the test below, the pointer of the ParamEmbeddedRec variable and the Params variable (inside ParamMaster) should be the same, so the value of PatchParam and Payload (inside ParamEmbeddedRec) are invalid. I think the syntax of line 47 (ParamMaster.Params := @ParamEmbedded) is not correct. Bellow, my code and an image of the debug, My code: unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); Type TParamMaster = Record Operacao : Smallint; Params : Pointer; End; Var ParamMaster : ^TParamMaster; Type TParamEmbedded = Record PatchParam : String; Payload : String; End; Var ParamEmbedded : ^TParamEmbedded; Var ParamEmbeddedRec : ^TParamEmbedded; begin New(ParamMaster); New(ParamEmbedded); ParamEmbedded.PatchParam := 'somePatch'; ParamEmbedded.Payload := '{"aooCode": "F60EB930-9B1B-11EF-9657-02240D86274B"}'; ParamMaster.Operacao := 1; ParamMaster.Params := @ParamEmbedded; ParamEmbeddedRec := ParamMaster.Params; Dispose(ParamEmbedded); Dispose(ParamMaster); end; end. Share this post Link to post
Remy Lebeau 1421 Posted December 5 (edited) 4 hours ago, John Gambler said: I'm having some difficulty using variables through their memory addresses. Because you are using it incorrectly. 4 hours ago, John Gambler said: In the test below, the pointer of the ParamEmbeddedRec variable and the Params variable (inside ParamMaster) should be the same They are the same address, but they are not the same type. The Params is holding a ^^TParamEmbedded (a pointer to a pointer to a record), but ParamEmbeddedRec is a ^TParamEmbedded (pointer to a record) instead. The only reason your code even compiles at all is because the Params is an untyped Pointer, so all type safety is out the window. 4 hours ago, John Gambler said: so the value of PatchParam and Payload (inside ParamEmbeddedRec) are invalid. I think the syntax of line 47 (ParamMaster.Params := @ParamEmbedded) is not correct. You are correct. You are storing a ^^TParamEmbedded into the Params, and then accessing it back out as a ^TParamEmbedded instead, eg: +------------+ +------------+ | Operacao | | PatchParam | | Params |---+ | Payoad | +------------+ | +------------+ ^ | ^ | | | +-------------+ | +---------------+ +------------------+ | ParamMaster | +-->| ParamEmbedded |<----| ParamEmbeddedRec | +-------------+ +---------------+ +------------------+ Get rid of the @, you don't need it since the ParamEmbedded variable is already a pointer, eg: procedure TForm1.Button1Click(Sender: TObject); Type TParamMaster = Record Operacao : Smallint; Params : Pointer; End; TParamEmbedded = Record PatchParam : String; Payload : String; End; Var ParamMaster : ^TParamMaster; ParamEmbedded : ^TParamEmbedded; ParamEmbeddedRec : ^TParamEmbedded; begin New(ParamMaster); New(ParamEmbedded); ParamEmbedded.PatchParam := 'somePatch'; ParamEmbedded.Payload := '{"aooCode": "F60EB930-9B1B-11EF-9657-02240D86274B"}'; ParamMaster.Operacao := 1; ParamMaster.Params := ParamEmbedded; // <-- NO @ HERE! ParamEmbeddedRec := ParamMaster.Params; ... Dispose(ParamEmbedded); Dispose(ParamMaster); end; +------------+ +------------+ | Operacao | | PatchParam | | Params |------->| Payload |<----------+ +------------+ +------------+ | ^ ^ | | | | +-------------+ +---------------+ +------------------+ | ParamMaster | | ParamEmbedded | | ParamEmbeddedRec | +-------------+ +---------------+ +------------------+ That being said, this example can be simplified by not using New/Dispose at all, in which case using @ does make sense, eg: procedure TForm1.Button1Click(Sender: TObject); Type TParamMaster = Record Operacao : Smallint; Params : Pointer; End; TParamEmbedded = Record PatchParam : String; Payload : String; End; Var ParamMaster : TParamMaster; ParamEmbedded : TParamEmbedded; ParamEmbeddedRec : ^TParamEmbedded; begin ParamEmbedded.PatchParam := 'somePatch'; ParamEmbedded.Payload := '{"aooCode": "F60EB930-9B1B-11EF-9657-02240D86274B"}'; ParamMaster.Operacao := 1; ParamMaster.Params := @ParamEmbedded; // <-- DO USE @ HERE! ParamEmbeddedRec := ParamMaster.Params; ... end; ParamMaster ParamEmbedded +------------+ +------------+ | Operacao | | PatchParam | +------------------+ | Params |---->| Payload |<----| ParamEmbeddedRec | +------------+ +------------+ +------------------+ Edited December 5 by Remy Lebeau 1 Share this post Link to post
John Gambler 0 Posted December 5 Perfect. I'm glad I didn't find this one in my attempts, otherwise I wouldn't have had access to such a comprehensive explanation. I use this approach to access a DLL from my application. This DLL only exports one function, which receives a pointer and returns a pointer. ParamMaster represents the generic parameter for the DLL. ParamMaster.Operation represents which service from the DLL I want to use and ParamMaster.Param represents the parameter used by this service. The DLL returns a pointer that represents the response from this service. Right after calling the service, the caller copies the response to internal variables and calls the DLL again to inform it that it no longer needs the response variable and the DLL calls a dispose for it. Right after, the caller disposes the parameter variable. I don't know if I was clear. In any case, I'm satisfied with the quick and objective response. Thank you. Share this post Link to post