delphi - Interface DLL form app crashing -
i have problem host application, loads dll form , interfaceing function , properties.
the purpose load dll, show name module name, set connection adotable component , show form data. working fine. after close host app host app crashed , windows hostapp.exe stopped working.
i not know whether freeing library or setting nil interface.
do have solution? thanks.
interface code
unit u_baseplugin_intf; interface uses data.win.adodb, data.db; type ibasemoduleinterface = interface ['{060a9c46-b3cf-4ba4-b025-2dc1d9f45076}'] function getmodulename: ansistring;stdcall; procedure setconn(sconn:tadoconnection);stdcall; procedure showf;stdcall; procedure freef;stdcall; property modulename: ansistring read getmodulename; property connection : tadoconnection write setconn; end; implementation end.
dll code
library profileslist; uses system.sysutils, system.classes, u_baseplugin_intf, u_profileslist in 'u_profileslist.pas' {form_dll}; {$r *.res} function loadmodule:ibasemoduleinterface;stdcall; begin result:=tform_dll.create(nil); end; exports loadmodule; begin end.
dll form code
unit u_profileslist; interface uses winapi.windows, winapi.messages, system.sysutils, system.variants, system.classes, vcl.graphics, vcl.controls, vcl.forms, vcl.dialogs, vcl.grids, vcl.dbgrids, vcl.stdctrls, u_baseplugin_intf, data.db,data.win.adodb; type tform_dll = class(tform, ibasemoduleinterface) dbgrid1: tdbgrid; adotable1: tadotable; datasource1: tdatasource; procedure formshow(sender: tobject); procedure formclose(sender: tobject; var action: tcloseaction); private { private declarations } {interface methods implementation} function getmodulename: ansistring;stdcall; procedure setconn(sconn:tadoconnection);stdcall; public { public declarations } {interface methods implementation} procedure showf;stdcall; procedure freef;stdcall; end; var form_dll: tform_dll; implementation {$r *.dfm} {interface methods implementation} function tform_dll.getmodulename; begin result := 'profiles list'; end; procedure tform_dll.setconn(sconn: tadoconnection); begin adotable1.connection:=sconn; end; procedure tform_dll.showf; begin showmodal; end; procedure tform_dll.freef; begin freeandnil(form_dll); end; {form_dll methods implementation} procedure tform_dll.formclose(sender: tobject; var action: tcloseaction); begin adotable1.active:=false; end; procedure tform_dll.formshow(sender: tobject); begin adotable1.active:=true; end; end.
host app code
program hostapp; uses vcl.forms, u_hostapp in 'u_hostapp.pas' {form1}, u_baseplugin_intf in 'u_baseplugin_intf.pas'; {$r *.res} begin application.initialize; application.mainformontaskbar := true; application.createform(tform1, form1); application.run; end.
host app form code
unit u_hostapp; interface uses winapi.windows, winapi.messages, system.sysutils, system.variants, system.classes, vcl.graphics, vcl.controls, vcl.forms, vcl.dialogs, vcl.stdctrls, vcl.extctrls, u_baseplugin_intf, data.win.adodb, data.db; type tform1 = class(tform) adoconnection1: tadoconnection; button1: tbutton; label1: tlabel; procedure button1click(sender: tobject); procedure formclose(sender: tobject; var action: tcloseaction); procedure formcreate(sender: tobject); private { private declarations } public { public declarations } end; type tmoduleinterface = function:ibasemoduleinterface; stdcall; var form1: tform1; implementation {$r *.dfm} var amoduleintf : ibasemoduleinterface; dllhandle : cardinal; procedure loadmodule( alibname : pwidechar ); var lmodule : tmoduleinterface; begin dllhandle := loadlibrary(alibname) ; if dllhandle <> 0 begin @lmodule := getprocaddress(dllhandle, 'loadmodule') ; if assigned (lmodule) amoduleintf := lmodule //call function else begin showmessage('getmoduleintf not found.') ; freelibrary(dllhandle) ; end; end else begin showmessage(alibname+' not found.') ; end; end; procedure tform1.button1click(sender: tobject); begin amoduleintf.connection:=adoconnection1; amoduleintf.showf; end; procedure tform1.formclose(sender: tobject; var action: tcloseaction); begin amoduleintf.connection:=nil; amoduleintf.freef; amoduleintf:=nil; freelibrary(dllhandle); end; procedure tform1.formcreate(sender: tobject); begin loadmodule('profileslist.dll'); label1.caption:=amoduleintf.modulename; end; end.
you never assign form_dll
. means when call freef
, perform freeandnil(form_dll)
. since form_dll
nil
, nothing, , form still exists.
fix changing loadmodule
:
function loadmodule:ibasemoduleinterface;stdcall; begin assert(not assigned(form_dll)); form_dll:=tform_dll.create(nil); result:=form_dll; end;
although, i'd change design removing form_dll
altogether. host app maintains reference form, on call free
can made. in other words, remove form_dll
, implement freef
this:
procedure tform_dll.freef; begin free; // or destroy end;
or better, use reference counted interfaces on implementing object , let amoduleintf:=nil
take form down.
Comments
Post a Comment