我有一个多线程应用程序,可以动态加载dll(插件)。我在DLL中有线程。主机应用程序和DLL之间是我自己的SDK,目的是启用与DLL插件(库接口)的通信,并定义主机应用程序和dll(数据结构等)之间的共享资源。
主机应用程序正在使用WinAPI函数CreateMutex创建一个互斥对象,并将已创建的互斥锁的THandle传递给我加载的每个dll。当DLL中的线程正在更改公共资源时,它使用互斥锁来保护它。正如我所说,我使用WinAPI.Windows单元调用CreateMutex和所有其他互斥相关的函数(Release等..)。
我的想法是制作SDK跨平台,因此我即将修改SDK,我想摆脱单位WinAPI.Windows和所有Windows相关的东西当然。
我包含System.SyncObjs以使用TMutex类。现在我不太确定如何让我知道关于那门课的问题。一种选择是将TMutex传递给我的DLL,但我认为如果我想在我的SDK中保留原始数据类型,这不是一个选项,因为SDK必须可用于其他语言,如C ++,C#...等其他想法穿过我的介意是使用命名的互斥锁,只需将名称(字符串)传递给DLL。
根据MSDN:如果互斥锁是一个命名的互斥锁,并且该函数调用之前存在该对象,则返回值是现有对象的句柄,GetLastError返回ERROR_ALREADY_EXISTS,忽略bInitialOwner,调用线程为未授予所有权。但是,如果调用者具有有限的访问权限,则该函数将失败并显示ERROR_ACCESS_DENIED,并且调用者应使用OpenMutex函数。
所以我假设DLL在调用TMutex.Create(...,' MyMutex')时可以使用现有的名为mutex(MyMutex)。
我是对的吗?
感谢您的帮助和建议。我真的很感激!
答案 0 :(得分:2)
Windows互斥可以"共享"跨进程(在exe和DLL中更是如此) - 你有两种方法:
通常,Delphi中的API包装器太过限制了复杂的"场景。即使Delphi没有公开它们,直接使用Windows API也可以完全访问底层功能。转而之后,您将了解更多有关Windows如何工作的信息,而且您可以随时在Delphi外部进行回收......并且您不需要使用丑陋的黑客来包装不需要的东西包裹在界面等...
如果您需要跨平台功能,请为OS互斥体实现编写自己的包装器 - 不要依赖Delphi的包装器。
答案 1 :(得分:1)
不允许在运行时包之外的模块之间传递类实例。这不是一种有效的互操作形式。
所以我认为最干净的解决方案是用接口包装TMutex
。您可以在任何类型的模块之间传递接口,甚至是由不同编译器编译的模块。
有各种不同的互斥体可用,但在我看来,显而易见的选择是包裹TMonitor
。界面很简单:
type
IMutex = interface
procedure Acquire; stdcall;
procedure Release; stdcall;
end;
在可执行文件和DLL之间传递此接口是完全安全的。
实施可能如下:
type
TXplatMutex = class(TInterfacedObject, IMutex)
public
procedure Acquire; stdcall;
procedure Release; stdcall;
end;
procedure TXplatMutex.Acquire;
begin
TMonitor.Enter(Self);
end;
procedure TXplatMutex.Release;
begin
TMonitor.Exit(Self);
end;
您可以用这种方式包装您喜欢的任何互斥锁。我选择TMonitor
因为它在所有平台上都受支持,并且是Embarcadero库代码用于同步的主要工具。