3

i want to make dll that using tform as parameter, the simple plan is if that form passed to dll the dll file return array that contain components name.

it possible to passing tform as parameter?

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
AsepRoro
  • 353
  • 2
  • 6
  • 19

2 Answers2

6

Most likely you will have two instances of the VCL in your process, one for the host exe and one for the DLL. And that is one instance too many. The TForm class from your host exe is a different class from the TForm class in your DLL.

The basic rule is that you cannot share VCL/RTL objects across module boundaries unless all modules use the same instance of the VCL/RTL runtime. The way to make that happen is to link to the VCL/RTL using packages.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • hi david, as my question my dll to get component list work without error, but if i assign component with "as" Tsomecomponent i get error. i'm still confusing about that – AsepRoro Mar 11 '13 at 08:38
1

I'll assume you have a framework where you have a TMemo on the form:

Declare two types:

type
  PTform                                  = ^TForm;
  TStringArray                            = array of string;

and make these visible to both the EXE and the DLL

.DPR implementation section:

procedure dllcomplist(p_pt_form : PTForm;
                  var p_tx_component : TStringArray);
          stdcall;
          external 'dllname.dll';

...

var
  t_tx_component                          : TStringArray;
  t_ix_component                          : integer;

...

  Memo1.Lines.Add('Call DLL to return componentlist');
  dllcomplist(pt_form,t_tx_component);
  Memo1.Lines.Add('Result in main program');
  for t_ix_component := 0 to pred(length(t_tx_component)) do
    Memo1.Lines.Add(inttostr(t_ix_component) + '=' + t_tx_component[t_ix_component]);
  setlength(t_tx_component,0);

and in the DLL's .DPR

...

procedure dllcomplist(p_pt_form : PTForm;
                  var p_tx_component : TStringArray);
          stdcall;
var
  t_ix_component                          : integer;
  t_ix_memo                               : integer;
  t_tx_component                          : TStringArray;
begin with p_pt_form^ do begin
  setlength(t_tx_component,componentcount);
  setlength(p_tx_component,componentcount);
  for t_ix_component := 0 to pred(componentcount) do
  begin
    t_tx_component[t_ix_component] := components[t_ix_component].Name;
    p_tx_component[t_ix_component] := components[t_ix_component].Name;
    if components[t_ix_component].ClassName = 'TMemo' then
      t_ix_memo := t_ix_component;
  end;
  Tmemo(components[t_ix_memo]).lines.add('Within DLL...');
  for t_ix_component := 0 to pred(componentcount) do
    Tmemo(components[t_ix_memo]).lines.add(inttostr(t_ix_component) + ' ' 
            + t_tx_component[t_ix_component]);
  Tmemo(components[t_ix_memo]).lines.add('DLL...Done');
  setlength(t_tx_component,0);
end;
end;

...

exports dllcomplist;

{OK - this is way more complicated than strictly needs be. What I'm doing is establishing a dynamic array in the calling program, filling it in the DLL then displaying the result in the caller

AND

detecting the TMemo in the DLL and writing the data from an identical dynamic array in the DLL to the TMemo from the caller - to show the data is identical}

Magoo
  • 77,302
  • 8
  • 62
  • 84