Solved

Problems in integrating VCL & FireMonkey via a FM DLL

Posted on 2014-09-12
4
588 Views
Last Modified: 2014-09-14
I have written a Fire Monkey (mobile phone) application that also runs on Windows. So far so good.

Although it is not recommended by Embarcadero, I also have been able to compile the Fire Monkey into a VCL project. They don't interact, apart from the VCL calling the main frame of the Fire Monkey app, and then receiving back control when all is complete.

It is a little ugly at the user interface end, in that the Fire Monkey app also appears on the windows task bar, even when it is not running.

Also when I tested it on Vista I get an exception on closing the VCL.

Therefore, following Embarcadero's recommendation, I have written a DLL interface that embodies the Fire Monkey component. However I am doing something wrong, because as soon as I carry out a task in a sub-unit referencing the main form I get a data exception.

library LangDLL;

uses
  FMX.Forms,
  System.SysUtils,
  System.Classes,
  uMMain in 'uMMain.pas',
  uMAccess in 'uMAccess.pas',
  uUnique in 'uUnique.pas';

{$R *.res}

procedure ShowMobile; stdcall export;
var
  MM: TfMMain;
  test: string;
begin
  test := 'OK';
try
  MM := TfMMain.Create(application);
  MM.FormActivate(application);
  MM.Free;
except
  test := 'Failed';
end;
end;
exports
  ShowMobile;
begin
end.

Open in new window


It passes through the above code without a worry, and in the main part of the App it works OK.

I have a couple of units that are called by the program. When the logic flows to those units in the DLL style operation the form fMMain is now nil to them. (It is OK when it runs as a stand-alone program.)

The simple work-around would be eliminate those units, but why is fMMain = nil in this situation?
0
Comment
Question by:GrahamDLovell
  • 2
  • 2
4 Comments
 
LVL 25

Expert Comment

by:Sinisa Vuk
ID: 40321261
fMMain  is defined as TfMMain in uMMain unit? Why do you mix fmx/vcl code?
0
 

Author Comment

by:GrahamDLovell
ID: 40321370
I just gave the form the name fMMain (form, mobile, main)

The default for a new form in fmx is Form1. The IDE adds the T prefix for a type. The same pattern is followed here.

How have I mixed fmx / vcl code?
0
 
LVL 25

Accepted Solution

by:
Sinisa Vuk earned 500 total points
ID: 40322113
I build small example with some success:

Dll part  (delph->new library):
library test1;

uses
  FMX.Forms,
  System.SysUtils,
  System.Classes,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

procedure ShowMobile; stdcall;
var
  MM: TForm1;
  test: string;
begin
  test := 'OK';
try
  MM := TForm1.Create(nil);
  try
    MM.ShowModal;
  finally
    MM.Free;
  end;
except
  test := 'Failed';
end;
end;
exports
  ShowMobile;

begin

end.

Open in new window


...calling part:
uses ..., Unit3;

procedure TForm2.Button1Click(Sender: TObject);
begin
  StartForm;
end;

Open in new window


... unit3 where dll is loading dynamically ... and main thing here is to not call FreeLibrary by yourself:
unit Unit4;

interface

uses Winapi.Windows, System.SysUtils, Vcl.Forms;

type
  //user dll
  TFMXDllForm = procedure; stdcall;

function StartForm: Boolean;

var
  hDLLHandle: Cardinal = 0;  //global dll handle for reusing....

implementation

function StartForm: Boolean;
var
  sFileName: String;
  frm: TFMXDllForm;
begin
  Result := False;
  sFileName:=IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName))+'test1.dll';

  if hDLLHandle = 0 then //reuse dll handle
    hDLLHandle:=LoadLibrary(PChar(sFileName));
  if hDLLHandle <> 0 then
  begin
    try
      frm:=GetProcAddress(hDLLHandle, 'ShowMobile');

      if Assigned(frm) then
      begin
        frm;  //show dll form
        Result := True;
      end;
    except
    end;
  end;
end;

initialization

finalization
  //if hDLLHandle <> 0 then //do not free by own
  //  FreeLibrary(hDLLHandle);

end.

Open in new window

0
 

Author Closing Comment

by:GrahamDLovell
ID: 40322152
Brilliant. Works a charm.

For anyone else who tries this, here are some other things I learnt about FireMonkey DLLs:

This process instantiates the FireMonkey form, and so you have to do everything inside the form (no calls to functions or procedures that are not part of that form). - that is the answer to my original question.

Make sure you don't double reference the form, e.g. in a function TfMMain.GetList, don't reference a value as "fMMain.NewList", just use "NewList". While the former works in a standalone FireMonkey app, the DLL doesn't like it.

I also had to abandon using TFileStream in the DLL, but that is a matter for another question (but not from me, since I just used TClientDataSet.LoadFromFile instead).
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Learn to move / copy / export exchange contacts to iPhone without using any software. Also see the issues in configuration of exchange with iPhone to migrate contacts.
We have come a long way with backup and data protection — from backing up to floppies, external drives, CDs, Blu-ray, flash drives, SSD drives, and now to the cloud.
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now