Delphi / Win32的虚拟库接口? [英] Virtual Library Interfaces for Delphi/Win32?
问题描述
我阅读了这篇文章和找到虚拟库接口的概念,非常适合运行时加载DLL。但是似乎它们不适用于Win32。这是真的?如果是的话:为什么?我不明白什么会把想法与.NET结合起来。
I read this article and find the concept of Virtual Library Interfaces nice for runtime loading of DLLs. However it seems that they aren't available for Win32. Is this true? And if so: Why? I don't see what would tie the idea to .NET.
编辑:我已经在这里重写了Rob已经写过的内容了。 :-)
我不是在插件或类似的 - 这是关于简单的老Win32 DLL。对我来说,什么吸引人的想法是让编译器处理在运行时加载DLL的所有细节 - 不需要为DLL等中的每个函数调用GetProcAddress。
I'm mostly rephrasing here what Rob already wrote. :-)
I'm not after plugins or similar - it's about plain old Win32 DLLs. What appeals to me is the idea to let the compiler deal with all the details of loading a DLL at runtime - no need to call GetProcAddress for every function in the DLL etc.
推荐答案
在我看来,这三个答案到目前为止完全错过了你的问题。那个,还是我有你问为什么Win32 Delphi没有像哈维文章谈论的神奇的支持
功能,不是吗?也就是说,给定DLL的名称和接口的类型信息的函数返回一个使用从DLL导出的独立函数来实现该接口的对象。
It seems to me like the three answers so far have completely missed the point of your question. That, or I have. You're asking why Win32 Delphi doesn't have something like the magical Supports
function that Hallvard's article talks about, aren't you? Namely, a function that, given the name of a DLL and the type information of an interface, returns an object that implements that interface using the standalone functions exported from the DLL.
TJvPluginManager 要求插件DLL导出一个特殊的自我注册功能,管理员在加载DLL时将调用该函数,该函数必须返回 TJvPlugin
类,所以插件DLL必须用Delphi或C ++ Builder编写。另一方面,支持
功能适用于使用任何语言编写的任何DLL。你可以在kernel32上使用它,如果你愿意的话。
Hydra seems to be all about calling .Net code from a Win32 program, not about importing functions from a DLL. TJvPluginManager
requires that the plug-in DLLs export a special self-registration function that the manager will call when it loads the DLL, and the function must return an instance of the TJvPlugin
class, so the plug-in DLL must be written in Delphi or C++ Builder. The Supports
function, on the other hand, works with any DLL written in any language. You could use it on kernel32, if you wanted.
我不知道为什么Win32 Delphi没有这样的东西。可能CodeGear并没有看到很多的需求,因为Delphi和Turbo Pascal已经走了很久没有它。
I don't know why Win32 Delphi doesn't have such a thing. Maybe CodeGear didn't see much demand for it since Delphi and Turbo Pascal had already gone for so long without it.
当然有可能写一个类似于,而且我并不期望这个.Net版本一定要写得更难,除非微软的.Net库已经提供了大部分的功能,而且Delphi只是将它们包装成一个方便的调用函数像Delphi已有多年的支持
的其他几个重载版本。
It's certainly possible to write a function that works like that, and I don't expect it would be any harder to write than the .Net version must have been, unless Microsoft's .Net libraries already provide most of the pieces and Delphi just wraps them up into a convenient-to-call function that looks like the several other overloaded versions of Supports
that Delphi has had for years.
将有几个步骤在Win32中实现该功能。 (我只提供一个必要的草图,因为我现在没有Delphi的运行副本,很好地问,也许我会找到更多的细节。)首先,你需要确保类型一个接口的信息至少保留了其方法的未装饰名称。然后,支持
将需要为接口中的每个方法生成一个函数存根(除了_AddRef,_Release和QueryInterface)。假设调用约定是 stdcall
:
There would be a few steps to implementing that function in Win32. (I'm providing only a sketch of what's necessary because I don't have a running copy of Delphi handy right now. Ask nicely, and maybe I'll find more details.) First, you'd need to make sure that type information for an interface held, at a minimum, the undecorated names of its methods. Then, Supports
would need to generate a function stub for each method in the interface (besides _AddRef, _Release, and QueryInterface). The stub would go something like this, assuming the calling convention is stdcall
:
asm
// Pop the return address,
// discard the "this" pointer,
// and restore the return address
pop eax
pop ecx
push eax
jmp AddressOfFunction
end;
由于支持
生成每个存根,填写实际的函数地址,从调用 GetProcAddress
获取相应的接口方法的名称。 stdcall
调用约定很容易包装; cdecl
有点麻烦; 注册
是脖子上的痛苦。
As Supports
generated each stub, it would fill in the actual function address, gotten from calling GetProcAddress
with the name of the corresponding interface method. The stdcall
calling convention is easy to wrap like that; cdecl
is a little cumbersome; register
is a pain in the neck.
一旦生成了所有存根,就需要生成一个看起来它实现了给定的接口的对象。它不一定是一个实际的课。在编译时,支持
不知道将要求实现的接口的布局,所以有一个类不会太多。
Once it has all the stubs generated, it would need to generate an "object" that looks like it implements the given interface. It doesn't have to be an actual class. At compile time, Supports
doesn't know the layout of the interface it's going to be asked to implement, so having a class wouldn't accomplish much.
最后一步是提供 _AddRef
, _Release
的实现, QueryInterface
。 _AddRef
将不会显着; _Release
当引用计数达到零时,您可以调用 FreeLibrary
QueryInterface
根本不会做太多的事情,除了声称它支持 IUnknown
,并且给出的$ 支持
。
The final step is to provide implementations of the _AddRef
, _Release
, and QueryInterface
. _AddRef
would be unremarkable; _Release
is where you'd call FreeLibrary
when the reference count reached zero; QueryInterface
wouldn't do much at all, except claim that it supports IUnknown
and the interface given to Supports
.
Delphi曾经提供一个示例程序,演示了实现一个没有任何类的接口。所有这些都是使用记录和函数指针(完全是所有的接口)。 Delphi还带有相应的代码来做类,这部分是为了显示Delphi可以做多少事情。我现在找不到演示程序的名称,但我确定它仍然在某处。
Delphi used to come with a sample program that demonstrated implementing an interface without any classes at all. It was all done with records and function pointers (which is all an interface ultimately is, after all). Delphi also came with the corresponding code to do it with classes, in part to show how much easier Delphi can make things. I can't find the name of the demo program now, but I'm sure it's still around somewhere.
这篇关于Delphi / Win32的虚拟库接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!