Delphi 中如何将接口转换为对象
在delphi 2009中,我有一个对IInterface
的引用,我想将其转换为底层TObject
使用TObject(IInterface)
显然不起作用在Delphi 2009中(虽然它应该在Delphi 2010中工作)
我的搜索引导我到一个应该可以解决问题的函数,但它对我不起作用,当我尝试调用返回对象的方法时,我得到了 AV。
我无法真正修改类,而且我知道这会破坏 OOP
In delphi 2009 I have a reference to a IInterface
which I want to cast to the underlying TObject
Using TObject(IInterface)
obviously doesn't work in Delphi 2009 (it's supposed to work in Delphi 2010 though)
My searches lead me to a function that should do the trick, but it doesn't work for me, I get AV's when I try to call methods on the returned object.
I can't really modify the Classes and I know that this breaks OOP
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
你是对的。从 Delphi 2010 开始,您可以使用 as 运算符,例如通过
aObject := aInterface as TObject
甚至aObject := TObject(aInterface)
。此
as
运算符使用特殊的隐藏接口 GUID (ObjCastGUID
) 来检索对象实例,调用增强版本的TObject.GetInterface
,这会Delphi 2010 之前不存在。请参阅 System.pas 单元的源代码以了解其工作原理。我已经发布了一些适用于 Delphi 6 到 XE2 的代码,包括 Delphi 2009< /a>.
请参阅 http://blog .synopse.info?post/2012/06/13/从界面检索对象实例
You are right. Beginning with Delphi 2010, you are able to use the as operator, e.g. via
aObject := aInterface as TObject
or evenaObject := TObject(aInterface)
.This
as
operator use a special hidden interface GUID (ObjCastGUID
) to retrieve the object instance, calling an enhanced version ofTObject.GetInterface
, which does not exist prior to Delphi 2010. See source code ofSystem.pas
unit to see how it works.I've published some code working for Delphi 6 up to XE2, including Delphi 2009.
See http://blog.synopse.info?post/2012/06/13/Retrieve-the-object-instance-from-an-interface
除了依赖 Delphi 的内部对象布局之外,您还可以让对象实现另一个仅返回对象的接口。当然,只有当您首先有权访问对象的源代码时,这才有效,但如果您无权访问对象的源代码,您可能甚至不应该使用这些技巧。
Instead of relying on Delphi's internal object layout you could also have your objects implement another interface which would simply return the object. This, of course, only works if you have access to the source code of the objects to begin with, but you probably shouldn't even use these hacks if you don't have access the source code of the objects.
当您知道实现对象是
TComponent
后代时,有一个不错的选择。您可以使用
IInterfaceComponentReference
接口,该接口在Classes
单元中定义:然后在
TComponent
中声明(并实现以返回self
):因此,如果您知道实现对象是一个
TComponent
,那么您可以执行以下操作:There is a nice alternative when you know the implementing object is a
TComponent
descendant.You can use the
IInterfaceComponentReference
interface, which is defined up inClasses
unit:And then it's declared in
TComponent
(and implemented to returnself
):So if you know the implementing object is a
TComponent
then you can do this:简而言之:您不应该或添加一个带有为您返回指针的方法的接口。其他任何事情都是黑客行为。
请注意,接口“实例”可以用另一种语言实现(它们与 COM 兼容)和/或可以是进程外某些内容的存根等。
总而言之:接口实例仅同意该接口,而不同意其他任何内容,当然不是作为 Delphi TObject 实例实现的
In short: you shouldn't or add an interface with a method that returns the pointer for you. Anything else is hackery.
Note that an interface "instance" may be implemented in another language (they are COM compatible) and / or may be a stub for something out of process etc etc.
All in all: an interface instance only agrees to the interface and nothing else, certainly not being implemented as a Delphi TObject instance
Hallvard 的 hack 非常具体于 Delphi 编译器如何生成代码。这在过去一直非常稳定,但听起来他们在 Delphi 2009 中改变了一些重要的东西。我这里只安装了 2007,而 Hallvard 的代码工作得很好。
GetImplementingObject 返回 NIL 吗?
如果是这样,那么如果您在 GetImplementingObject 例程中的 case 语句上进行调试并设置断点,那么 QueryInterfaceThunk.AddInstruction 的值在调试器中的计算结果是什么?
Hallvard's hack is very specific to how the Delphi compiler generates code. That has been remarkably stable in the past, but it sounds like they changed something significant in Delphi 2009. I only have 2007 installed here, and in that, Hallvard's code works fine.
Does GetImplementingObject return NIL?
If so, then if you debug and set a break-point on the case statement in the GetImplementingObject routine, what does the value of QueryInterfaceThunk.AddInstruction evaluate to in the debugger?