gpt4 book ai didi

c - 如何从libXXX.so中内置的C(下层)调用Delphi函数(上层)?

转载 作者:太空宇宙 更新时间:2023-11-03 23:48:39 38 4
gpt4 key购买 nike

我有一个在 Android 上运行的 FMX 项目。我可以让 FMX 项目在“libTest.so”中执行一个 C 函数,如下所示:

ma​​in.pas:

TMyCallbackFun = procedure(Param: Integer) of object;

procedure TForm1.MyCallbackFun(Param: Integer);
begin
ShowMessage('MyCallbackFun called');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
Handle1: THandle;
fun1: function(MyCallbackFun: TMyCallbackFun): Integer; stdcall;
begin
Handle1 := LoadLibrary(PChar('/system/lib/libTestC.so'));
if Handle1 <> 0 then begin
fun1 := GetProcAddress(Handle1, PChar('RegisterCallback'));
if Assigned(fun1) then begin
Memo1.Lines.Add('RegisterCallback returns ' + IntToStr(fun1(MyCallbackFun)));
end;
end;
end;

TestC.c:

int (*RegisteredCallback)(int);
struct itimerval t;

void alarm_handler(int a) {
LOGD("alarm_handler called");

t.it_interval.tv_usec = 0;
t.it_interval.tv_sec = 0;
t.it_value.tv_usec = 0;
t.it_value.tv_sec = 0;

RegisteredCallback(8);
}

int RegisterCallback(void *CallbackFun)
{
LOGD("RegisterCallback called");

RegisteredCallback = CallbackFun;

t.it_interval.tv_usec = 0;
t.it_interval.tv_sec = 2;
t.it_value.tv_usec = 0;
t.it_value.tv_sec = 3;
setitimer(ITIMER_REAL, &t, NULL);
signal(SIGALRM, alarm_handler);

return 5;
}

我想让“libTest.so”中的C函数“RegisterCallback”保留“MyCallbackFun”的Delphi函数指针,然后在某个时间(比如定时器到期)“libTest.so”可以调用这个函数指针带参数。

但当计时器到期时它会崩溃:

10-28 19:17:55.161: D/TestC(673): RegisterCallback called
10-28 19:17:58.161: D/TestC(673): alarm_handler called
10-28 19:18:00.001: D/KeyguardUpdateMonitor(980): received broadcast android.intent.action.TIME_TICK
10-28 19:18:00.001: D/KeyguardUpdateMonitor(980): handleTimeUpdate
10-28 19:18:00.101: D/dalvikvm(31379): GC_CONCURRENT freed 382K, 75% free 2759K/10856K, paused 4ms+3ms, total 32ms
10-28 19:18:00.161: D/TestC(673): alarm_handler called
10-28 19:18:00.291: I/ActivityManager(980): Process com.embarcadero.ExternalLibrary (pid 673) has died.
10-28 19:18:00.291: I/WindowState(980): WIN DEATH: Window{41b7b560 u0 com.embarcadero.ExternalLibrary/com.embarcadero.firemonkey.FMXNativeActivity}
10-28 19:18:00.291: W/ActivityManager(980): Force removing ActivityRecord{41a03fe0 u0 com.embarcadero.ExternalLibrary/com.embarcadero.firemonkey.FMXNativeActivity}: app died, no saved state
10-28 19:18:00.311: D/Launcher(1348): Broadcasting Home Idle Screen Intent ...
10-28 19:18:00.321: D/CAT(1249): StkAppService: 7called on slot:0
10-28 19:18:00.321: D/CAT(1249): StkAppService$ServiceHandler: Need to send IDLE SCREEN Available event to SIM
10-28 19:18:00.321: D/CAT(1249): StkAppService$ServiceHandler: Event :5
10-28 19:18:00.321: D/CAT(1249): StkAppService$ServiceHandler: SetupEventList is not received. Ignoring the event: 5
10-28 19:18:00.351: D/Zygote(378): Process 673 terminated by signal (11)
10-28 19:18:00.371: W/InputMethodManagerService(980): Got RemoteException sending setActive(false) notification to pid 673 uid 10122
: E/(): Device disconnected

哪位专家可以告诉我如何修改代码以实现我的目标?

提前致谢!

最佳答案

TMyCallbackFun = procedure(Param: Integer) of object;

对象的 Delphi函数是一个方法指针。它是双指针类型。所以,SizeOf(TMyCallbackFun)=SizeOf(Pointer)*2。一个指针是实例,另一个是代码。调用该方法时,有一个额外的隐藏参数,它是实现内部的实例 Self。您不能在此处使用方法指针。你需要它是

TMyCallbackFun = procedure(Param: Integer); cdecl;

或者,很可能,如果您需要传递一个实例,那么这样做:

TMyCallbackFun = procedure(Param: Integer; Data: Pointer); cdecl;

在C端就是

void (*RegisteredCallback)(int, void*);

请注意,我将返回值从 int 更改为 void 以匹配 Delphi。而且我使用了 cdecl,因为我假设这是您的 C 编译器的默认调用约定。

您还需要存储数据以及回调:

void (*RegisteredCallback)(int, void*);
void *RegisteredCallbackData;
....
int RegisterCallback(void *CallbackFun, void *CallbackData)
{
....
RegisteredCallback = CallbackFun;
RegisteredCallbackData = CallbackData;
....
}

要从您执行的 C 代码中调用回调:

RegisteredCallback(..., RegisteredCallbackData);

在 Delphi 端,您可以像这样实现回调:

procedure MyCallbackFun(Param: Integer; Data: Pointer); cdecl;
begin
TForm1(Data).MyCallbackFun(Param);
end;

你需要声明 fun1 来匹配:

fun1: function(CallbackFun: TMyCallbackFun; CallbackData: Pointer): Integer; cdecl;

我想这就是一切!

关于c - 如何从libXXX.so中内置的C(下层)调用Delphi函数(上层)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26604719/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com