从 Delphi DLL 导出全局符号
我正在尝试在 Delphi 中创建一个与 Gecko 2.0 兼容的 DLL。
以前(Gecko 2.0 之前)DLL 需要导出 NSGetModule() 函数。这工作完美无缺。
从 Firefox 4 开始,我的 DLL 正在加载(我已经通过初始化部分中的断点验证了这一点),但我的 NSGetModule() 函数不再被调用。这是设计行为,因为从 Gecko 2.0 (Firefox 4) 开始,二进制组件不应导出 NSGetModule() 函数:
https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_2.0#Binary_components
根据这些文档,我的 DLL 需要导出一个 NSModule 数据符号,该符号指向到一个结构体。在 Delphi 术语中,我假设这是一个指向 Delphi 记录的全局变量。
在 C++ 中,这就是导出(全局)数据符号的方式:
define NSMODULE_DEFN(_name) extern "C" NS_EXPORT mozilla::Module const *const NSModule
我的问题:如何在 Delphi 中完成此操作?如何导出全局变量?
感谢您的反馈。
I'm trying to create a Gecko 2.0-compatible DLL in Delphi.
Previously (pre-Gecko 2.0) the DLL needed to export a NSGetModule() function. This worked flawlessly.
Starting with Firefox 4, my DLL is getting loaded (I have verified this though a breakpoint in my initialization section), but my NSGetModule() function does not get called anymore. This is the designed behavior because starting with Gecko 2.0 (Firefox 4), a binary component is not supposed to export a NSGetModule() function:
https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_2.0#Binary_components
According to these docs, my DLL needs to export a NSModule data symbol which points to a struct. In Delphi terminology, I assume this is a global variable which points to a Delphi record.
In C++, this is how you export the (global) data symbol:
define NSMODULE_DEFN(_name) extern "C" NS_EXPORT mozilla::Module const *const NSModule
My question: how do I accomplish this in Delphi? How do I export a global variable?
I appreciate your feedback.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
Delphi 从 DLL 导出全局变量的方式与导出函数的方式类似:
Delphi 可以从 DLL 导入全局变量,但这有点麻烦:声明一个与要导入的全局同名的 DLL 导入过程,然后获取程序的地址并进行适当调整。从Delphi 的角度来看,DLL 导入过程是通过DLL 导入表进行间接跳转的存根。导出的变量由操作系统加载器通过将导出的全局地址放入导入表中进行链接,几乎与导出过程的地址的修补方式完全相同。
例如:
当然,后者的细节取决于实现和平台等。也许更安全的方法是将
LoadLibrary
与GetProcAddress
一起使用,这将在传递全局变量的名称时返回全局变量的地址。当然,这也依赖于平台。64 位更新:
在 Windows 上的 64 位中,代码略有不同。操作码相同,但同一指令序列的寻址方式不同;它不是 32 位绝对偏移,而是 32 位相对偏移。
Delphi exports global variables from DLLs in a similar way to how it exports functions:
Delphi can import global variables from DLLs, but it's a bit of a hack: declare a DLL import procedure of the same name as the global to import, then get the address of the procedure and adjust it appropriately. DLL imported procedures, from Delphi's perspective, are stubs that do an indirect jump through the DLL import table. Exported variables are linked by the OS loader by putting the address of the exported global in the import table, almost exactly like how addresses of exported procedures are similarly patched in.
For example:
Of course, the latter details are implementation and platform dependent etc. Probably a safer approach is to use
LoadLibrary
withGetProcAddress
, which will return the address of the global variable when passed its name. Of course, that's also platform dependent.64-bit update:
In 64-bit on Windows, the code is slightly different. The opcodes are the same, but the addressing mode for the same instruction sequence is different; instead of a 32-bit absolute offset, it's a 32-bit relative offset.
阅读文档,我认为 Delphi 不允许直接导出全局变量,因为导出语句的帮助仅讨论例程。还有一个非常明确的
并且可以安全地假设,如果 Delphi 无法导入它们,它也不会导出它们。
我想解决这个问题的方法可能是导出一个返回指向全局变量的指针的函数...
仅此几行:
所以,如果 NSGetModule 函数返回与您现在需要导出为全局变量相同的结构,您可以尝试使用要导出的全局变量所需的名称来导出该函数:
Reading the docs, I don't think Delphi allows for the export of global variables directly as the help on the exports statement discusses only routines. Also there is a very definite
and it is probably safe to assume that if Delphi can't import them, it also won't export them.
I suppose the way around this could be to export a function that returns a pointer to the global variable...
Something alone the lines of:
So, if the NSGetModule function returns the same struct as you are now required to export as a global variable, you could try to export that function with a name as required for the global var to be exported:
这是我的德尔福解决方案。即使在 D5 中它也能工作:)
现在如果你可以向我发送 Delphi 中的 GenericClassInfo 实现,那就太棒了:)
Here is my Delphi solution. And it works even in D5 :)
Now if you can send me GenericClassInfo implementation in delphi that would be awesome :)
正如您所注意到的,这在 FF 5 和 FF 6 中不起作用。相反,您可以添加初始化块来在运行时检查 Firefox 版本,并相应地调整 mVersion。
Mozilla 有意破坏二进制组件,因此即使在不同版本之间,这也是一个可行的解决方法。
您可以使用 Application.ExeName 和 http://www.delphitricks.com/source- code/files/get_the_version_of_a_file.html
FF 5 - mVersion := 2;
FF 6 - m版本 := 6;
FF 7 - m版本 := 7;
As you have noticed this does not work in FF 5 and FF 6. Instead you can add initialization block to check for firefox version at runtime at adjust mVersion accordingly.
Mozilla is intentionally breaking binary components, so this is a workable workaround even between different versions.
You can use Application.ExeName and http://www.delphitricks.com/source-code/files/get_the_version_of_a_file.html
FF 5 - mVersion := 2;
FF 6 - mVersion := 6;
FF 7 - mVersion := 7;
这是我当前的实现(这适用于 FF 5 和 FF 6 以及可能未来的所有其他版本)
Here's my current implementation (this works in FF 5 and FF 6 and probably all others going forward)