如何为 DLL 提供相互依赖并公开功能的框架?

发布于 2024-09-24 17:11:31 字数 262 浏览 2 评论 0原文

本质上就是如何编写一个插件系统,其中每个插件都是一个DLL。 (或者是否有更好的插件系统方法,其中每个插件都是本机编写的?)

假设每个 DLL 都提供一些其他插件可用的功能。如果插件 A 确实提供了 FuncA 并且插件 B 想要 FuncA,那么应该如何管理依赖关系?插件应该如何识别(GUIDS?) DLL 应该如何加载?函数应该如何调用?

我不熟悉 DLL,并且我询问 Windows API 调用的范围,以便能够以合理的方式实现此目的。

Essentially, how to write a plugin system, where each plugin is a DLL. (Or is there a better way of a plugin system where each plugin is written natively?)

Suppose that each DLL offers some functionality available to other plugins. If plugin A does provides FuncA and plugin B wants FuncA, how should dependency be managed? How should plugins be identified (GUIDS?) How should be DLLs loaded? How should the function be called?

I'm not familiar with DLLs, and I am asking on the scope of Windows API calls that would enable a sane way to achieve this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

幻想少年梦 2024-10-01 17:11:31

让您的 DLL 导出一个函数,返回有关插件本身的元信息,即版本、依赖项、导出的功能等。当遍历插件目录时,通过 LoadLibrary 动态加载该目录中的 DLL 并检查它们是否存在导出与您的查询函数匹配的符号(通过GetProcAddress)。如果是这样,请加载 DLL,尝试查询插件并从中获取一些有意义的信息。

请务必为您的插件系统采用某种版本管理,以适应 API 更改。 Windows 本身通过将版本信息(有时以结构大小的形式)传递给某些函数来实现这一点。

至于依赖关系,构建依赖关系图。如果您检测到循环依赖(例如使用 Floyd 算法),请询问用户该怎么做,即要禁用什么插件。如果图表中没有循环,您可以遍历(有向)图表来确定插件的加载顺序。

根据评论中的问题进行编辑:

DLL1如何调用它的函数
期望在 DLL2 中?我猜
插件框架需要提供
类似的东西
GetPluginFuncAddr(plugin_ID, func_ID)
[...]

是的,您可以公开这样的函数,或者提供对某种全局可访问注册表的访问。再次,我建议包括版本控制,因此插件可以选择要求已知可用的功能的特定版本,从而允许更新而不会破坏现有插件。

插件和功能应该如何
确定了?字符串与 GUID,或者是
这对于插件来说是一件微不足道的事情
应该只提供标题吗?

看,如果您正在使用另一个插件的特性/功能开发插件,您可能不想在每次编写插件时都进行插件加载、版本/兼容性检查和错误处理,相反,您可能希望链接到为您执行样板内容的存根。至于如何实现插件和功能识别实际上取决于您。在识别插件(以及用户友好的、人类可读的名称和描述)时,GUID 肯定不是一个坏主意,除此之外,您还可以提供不同功能版本的列表/树,即

UsefulPlugin@{1e2f253e-a3b2-4617-90f2-f323577ffddf}
|
\__ FunctionA
| |
| \_ v1.1
| |
| \_ v1.3
|
\__ FunctionB
  |
  \_ v1.0

......客户可以查询需要的信息。如果需要,您甚至可以提供反射类型的信息,提供有关函数的参数、返回值等的信息。

Have your DLL export a function returning meta information about the plugin itself, i.e. version, dependencies, exported features etc. When walking over a plugin directory, dynamically load the DLLs in that directory via LoadLibrary and check if they export a symbol that matches your query function (via GetProcAddress). If so, load the DLL, try to query the plugin and get some meaningful information out of it.

Be sure to employ some kind of version management for your plugin system, to accommodate for API changes. Windows itself does it by passing version information (sometimes in the form of struct sizes) to certain functions.

As for dependencies, build a dependency graph. If you detect a circular dependency (for example using Floyd's algorithm), ask the user what to do, i.e. what plugin to disable. If there are no cycles in your graph, you can traverse the (directed) graph to determine a load order for plugins.

Edit, as per your question in the comment:

How would DLL1 call a function that it
expects in DLL2? I'm guessing the
plugin framework would need to provide
something like
GetPluginFuncAddr(plugin_ID, func_ID)
[...]

Yes, you could expose a function like this, or provide access to some sort of globally accessible registry. Again, I would advise to include versioning, so plugins can optionally ask for a specific version of a function that is known to work, allowing updates without breaking existing plugins.

how should plugins and functions be
identified? Strings vs GUIDs, or is
this a trivial thing since a plugin
should just provide headers?

See, if you are developing a plugin using features/functions of another plugin, you probably don't want to do the plugin loading, version/compatiblity checking and error handling each time you write a plugin, instead, you'd probably expect to link against a stub that does the boilerplate stuff for you. As for how you implement plugin and function identification really is up to you. GUIDs sure are not a bad idea when it comes to identifying a plugin (together with a user-friendly, human readable name and description), apart from that, you can offer a list/tree of different feature versions, i.e.

UsefulPlugin@{1e2f253e-a3b2-4617-90f2-f323577ffddf}
|
\__ FunctionA
| |
| \_ v1.1
| |
| \_ v1.3
|
\__ FunctionB
  |
  \_ v1.0

...which clients can query for needed information. If you want, you can even offer a reflection-kind of information, providing information about parameters, return values and the like of your function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文