delphi - Procedure in a component that uses another procedure in a DLL -
i having problem trying create procedure component uses procedure contained in dll (texecute) needs declaration in current code. procedure has pointer parameter know evaluation. following code works fine need procedure eval inside component use private variables component. working code following, note eval procedure global in case.
texecute = procedure(eval: pointer, var variablearray: double);cdecl tmycomponent = class(tcomponent) public fhandle: thandle; fexecute: texecute; procedure calculate; var n: integer; x: array of double; procedure eval(var x: double); implementation procedure eval(var x:double); var mx: array[0..200] of double absolute x; begin mx[0]:= 2*mx[0]; end; tmycomponent.calculate; begin fhandle:= loadlibrary(.....); fexecute:= getprocaddress(fhandle, 'main'); n:=2; setlength(x,n); fexecute(@eval,x[0]); end;
i got problem when put procedure eval inside tmycomponent that:
texecute = procedure(eval: pointer, var variablearray: double);cdecl tmycomponent = class(tcomponent) public fhandle: thandle; fexecute: texecute; procedure calculate; procedure eval(var x: double); var n: integer; x: array of double; implementation procedure tmycomponent.eval(var x:double); var mx: array[0..200] of double absolute x; begin mx[0]:= 2*mx[0]; end; tmycomponent.calculate; begin fhandle:= loadlibrary(.....); fexecute:= getprocaddress(fhandle, 'main'); n:=2; setlength(fx,n); fexecute(@tmycomponent.eval,x[0]); end;
i project faulted message: access violation @ 0x65900381f: write of address 0x0000005c. process stopped. use setp of run continue.
and don't have no clue problem, tried change , did't solution. if me appreciate.
a global procedure , class method not same thing. class method has hidden self
parameter, dll not take account when class method passed dll. why code crashes - call stack not set correctly.
given "working" code, component code needs this:
texecute = procedure(eval: pointer; var variablearray: double); cdecl; tmycomponent = class(tcomponent) public fhandle: thandle; fexecute: texecute; procedure calculate; class procedure eval(var x: double); static; end; var n: integer; x: array of double; implementation class procedure tmycomponent.eval(var x:double); var mx: array[0..200] of double absolute x; begin mx[0]:= 2*mx[0]; end; procedure tmycomponent.calculate; begin fhandle:= loadlibrary(.....); fexecute:= getprocaddress(fhandle, 'main'); n:=2; setlength(fx,n); fexecute(@eval,x[0]); end;
since eval()
method accesses global variable, works fine. if needs access members of component, have problem since static
directive eliminates self
parameter. in case, have 3 options.
if can, change dll function accept additional parameter component can pass
self
value in, , have dll pass valueeval()
parameter, eg:texecute = procedure(eval: pointer, var variablearray: double; userdata: pointer); cdecl; tmycomponent = class(tcomponent) public fhandle: thandle; fexecute: texecute; procedure calculate; class procedure eval(var x: double; userdata: pointer); static; end; var n: integer; x: array of double; implementation class procedure tmycomponent.eval(var x: double; userdata: pointer); begin // use tmycomponent(userdata) needed... end; procedure tmycomponent.calculate; begin fhandle:= loadlibrary(.....); fexecute:= getprocaddress(fhandle, 'main'); n:=2; setlength(fx,n); fexecute(@eval, x[0], self); end;
if #1 not possible, , if there 1 instance of component calling dll function @ time, use global pointer component, eg:
texecute = procedure(eval: pointer, var variablearray: double); cdecl; tmycomponent = class(tcomponent) public fhandle: thandle; fexecute: texecute; procedure calculate; class procedure eval(var x: double); static; end; var n: integer; x: array of double; implementation var mycomp: tmycomponent; class procedure tmycomponent.eval(var x: double); begin // use mycomp needed... end; procedure tmycomponent.calculate; begin fhandle:= loadlibrary(.....); fexecute:= getprocaddress(fhandle, 'main'); n:=2; setlength(fx,n); mycomp := self; fexecute(@eval, x[0]); end;
if #2 not possible because multiple component instances need call dll @ same time, option left use dynamic proxy. allocate block of executable memory , store special stub code in along component
self
pointer, pass memory block dll if normal procedure. when dll calls "procedure", it's stub code called, can extract component pointer proxy , use needed. approach vcl uses assigning non-statictwincontrol.wndproc()
method win32 api window procedure callbacks. can't provide code here right now, in vcl's source code @classes.makeobjectinstance()
function example.
Comments
Post a Comment