macos - 无法注册类 TFMXApplicationDelegate
问题描述
我已经阅读了 Embarcadero 和其他文档,搜索了网络,显然有些东西并没有陷入困境。我有一个复杂得多的应用程序和 DLL/Dylib,但现在我只是使用这个简单的例子来尝试让它工作. 当我为 Win32 构建应用程序和 DLL 时,它工作正常,如果我不对 DLL 进行函数调用,它工作正常。一旦我调用 DLL,就会引发错误 Unable to register Class TFMXApplicationDelegate 并且应用程序终止。无论客户操作系统是在 VM(并行)还是物理设备(MacBook Pro 15 mid-2015)上,此行为都是相同的。
问题:如何确保TFMXApplicationDelegate 已注册,是否需要设置设置或权限。根据Apple文档,这似乎相当基本:
应用程序委托实际上是应用程序的根对象。
民主共和国:
Library pTestDLL;
uses
uTestDLL in 'uTestDLL.pas';
{$R *.res}
end.
这是简单的 PAS 文件(用于 Dylib):
unit uTestDLL;
interface
uses
FMX.Dialogs;
// External functions and procedures
{$IFDEF MSWINDOWS}
function say_Hello(Hello: string): boolean; stdcall; forward;
{$ENDIF MSWINDOWS}
{$IFDEF MACOS}
function _say_Hello(Hello: string): boolean; cdecl; forward;
{$ENDIF MACOS}
exports
{$IFDEF MSWINDOWS}
say_Hello;
{$ENDIF MSWINDOWS}
{$IFDEF MACOS}
_say_Hello;
{$ENDIF MACOS}
Implementation
{$IFDEF MSWINDOWS}
function say_Hello(Hello: string): boolean; stdcall;
{$ENDIF MSWINDOWS}
{$IFDEF MACOS}
function _say_Hello(Hello: string): boolean; cdecl;
{$ENDIF MACOS}
begin
Result := True;
showmessage('In DLL: ' + Hello);
end;
end.
最后是简单的测试应用程序:
unit uDylibTest1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
FMX.Controls.Presentation;
const
// Windows DLL Names
{$IFDEF MSWINDOWS}
TestDLL = 'pTestDLL.dll';
{$ENDIF MSWINDOWS}
// macOS DYLIB Names
{$IFDEF MACOS}
TestDLL = 'libpTestDLL.dylib';
{$ENDIF MACOS}
type
TfDylibTest = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
TuDylibTest = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
{$IFDEF MSWINDOWS}
function say_Hello(Hello: string): boolean; stdcall; external TestDLL Delayed;
{$ENDIF MSWINDOWS}
{$IFDEF MACOS}
function _say_Hello(Hello: string): boolean; cdecl; external TestDLL;
{$ENDIF MACOS}
var
fDylibTest: TfDylibTest;
implementation
{$R *.fmx}
procedure TfDylibTest.Button1Click(Sender: TObject);
var
b:boolean;
begin
showmessage('B4 function call);
b := False;
// Call the DLL Function
{$IFDEF MSWINDOWS}
b := say_Hello('The string passed to the DLL') then
{$ENDIF MSWINDOWS}
{$IFDEF MACOS}
b := _say_Hello('The string passed to the DLL');
{$ENDIF MACOS}
if b then
showmessage('Say Hello OK')
else
showmessage('Say Hello Failed');
end;
procedure TfDylibTest.FormCreate(Sender: TObject);
begin
showmessage('onCreate');
end;
procedure TfDylibTest.FormShow(Sender: TObject);
begin
showmessage('onShow');
end;
end.
解决方案
我代表 Alexander Brazda López 回答这个问题,他在 G+ Delphi 论坛上发布了这个问题(所以我不会把别人的回答归功于自己):
ShowMessage() 在 dll 中使用 FMX.Dialogs。我记得对此有一些限制,建议使用 bpl 代替 dll。我会尝试找到一些有关此的信息。只是为了检查,尝试使用反向字符串函数来测试打开和调用 dll 函数的工作。
我无法评论 WRT 下一部分回复的真实性,但公平地说,将包括它。然而,底线是使用子句中的 FMX.Dialogs 或 FMX.Forms,我得到了错误。删除这些并且没有发生 TFMXApplicationDelegate 错误。
在非平凡的“真实”示例中,我使用的单元 forshowmessage
和 for application.processmessages
which 在一个名为的跨平台函数WaitNoFreeze()
中,顾名思义,它在主线程中放置一个等待,但不会停止所有其他活动,如sleep()
.
问题不在于找不到dylib,这可以通过调用dylib中的一个基本函数作为函数sum(a,b:integer)来检查:integer
问题是当我们通过某些函数调用 UI 或使用表单等嵌入式资源时。这是因为如果我们不使用 bpl,则会创建本地实例而不是共享全局实例,这会阻止 RegisterClass 或 GetMem 等函数共享数据。在 FMX 的情况下,由于 Kevin 公开的示例的 api 存在差异,在 Windows 中窗口的句柄不是必需的,因此 0 是有效值,在 MacOSX 中是必需的,但 dynlib 中的值是NULL 因为它没有被启动,虽然在应用程序中,但是因为 FMX 实例没有共享,所以不可能访问这个信息。当我们尝试在 Windows 中的 dll 中释放已由应用程序分配的内存块时,会发生同样的事情,
推荐阅读
- java - Observable.map 抛出的错误没有被订阅捕获
- javascript - 如何更改 Darksky API 请求的时间格式?
- telegram - 如何以编程方式获取 Telegram Bot 的信息
- amazon-dynamodb - 提供的关键元素与架构不匹配 - updateItem
- html - 如何在内容和内容上使用不透明度::之前不重叠
- google-sheets - 计数范围内的行是否设置了两个条件
- apache-spark - spark xml:需要结构类型但得到字符串;
- ms-access - 使用 Ms Access LEFT JOIN 获取以前的余额作为欠款
- scala - Scala拆分序列或按分隔符列出
- vba - 收到错误“ByRef 参数类型不匹配”