【问题标题】:What to do with a COM server method returning an undocumented IUnknown如何处理返回未记录的 IUnknown 的 COM 服务器方法
【发布时间】:2012-12-03 18:23:38
【问题描述】:

我从类型库(硬件 SDK 的一部分)导入的 COM 接口的一些方法返回或接收 IUnknown 类型的值。例如,SDK 文档指定方法如下:

bool SetInput1Selection(InputSelection inputSelection)
InputSelection GetInput1Selection()

但 Delphi 像这样导入这些方法:

function SetInput1Selection(const inputSelection: IUnknown): WordBool; safecall;
function GetInput1Selection: IUnknown; safecall;

类型 InputSelection 似乎是一个简单的整数或枚举类型,但没有在任何地方指定。该文档仅提供了 14 种不同可能值及其含义的表格。

理想情况下,我想声明自己的类型:

TInputSelection = (isCustom, isStartReset, ...)

下面是类型库定义这些函数的方式:

virtual HRESULT __stdcall SetInput1Selection (/*[in]*/ IUnknown * inputSelection, /*[out,retval]*/ VARIANT_BOOL * pRetVal ) = 0;
virtual HRESULT __stdcall GetInput1Selection (/*[out,retval]*/ IUnknown * * pRetVal ) = 0;

但是我怎样才能做到这一点呢?

【问题讨论】:

  • 如果您知道类型库中的 InputSelection 类型是枚举并且您知道它的成员,只需在 Delphi 导入中更正它(按照您显示的方式)。这可能只是错误的导入。
  • @TLama 我尝试用 Integer 代替 TLB 单元中的 IUnknown。但是GetInput#Selection 返回的值似乎与任何允许的值都不对应。它们甚至不映射 1:1,这意味着对于设置了不同值的输入通道返回相同的值(SDK 包含一个测试应用程序,我可以使用它读取/写入输入通道设置)。这里似乎发生了更多事情。有没有“正确”的方式来做到这一点?
  • 既然不知道SDK你自己看吧,SDK是什么类型的。如果文档中不清楚,您应该询问 SDK 开发人员
  • 我有。显然,他们将 sdk 开发外包,现在无法提供任何开发人员支持。不是我购买他们的硬件时所期望的。但现在我必须尽力而为。是否有一些取证方法可以找出如何处理这样的 IUnknown 参数?
  • 我在第一条评论中试图说的(或者更好地说是猜测,没有看到你的类型库)是 Delphi 导入器可能在导入该参数时失败,你应该修改你的 Delphi手动导入(如果你知道参数是枚举而不是接口)。

标签: .net delphi interface iunknown


【解决方案1】:

整数/枚举和接口在 TypeLibrary 中的描述不同,因此 TypeLibrary 导入器不太可能混淆它们。我的猜测是InputSelection 确实是一种封装了其他数据的接口类型,并且可能具有自己的属性/方法来访问该数据。如果该接口没有出现在 TypeLibrary 中,那么它可能是一个私有接口。

您可以尝试的一件事是在GetInput1Selection() 返回的IUnknown 上调用QueryInterface(),要求它提供IDispatch 接口。如果崩溃,那么IUnknown 不是一个有效的接口指针,这将回到可能的错误导入。但如果它没有崩溃,它很可能是一个真正的接口,尤其是如果QueryInterface() 成功。如果是,请致电IDispatch.GetTypeInfo() 以查看它是否描述了自己。如果是这样,您可以发现接口实现的所有属性和方法,包括参数。在某些环境中,如果基于IDispatch 的对象只是一个POD 值的包装器,如整数,它通常具有Value 属性,甚至还有一个特殊的DISPID 用于访问这样的属性@987654333 @(我不记得实际的DISPID 号码,我得查一下)。

更新:您是否有机会对 Nanotec 步进电机进行编程?我在网上找到了documentation,与您提到的功能相似:

GetInput1Selection
    Definition:
        InputSelection GetInput1Selection()

This function outputs the function for digital input 1.
The function corresponds to serial command ':port_in_a'.

SetInput2Selection
    Definition:
        bool SetInput2Selection(InputSelection inputSelection)

This function sets the function for digital input 2.
The value returned by the function can be used to check that the command was correctly recognized by the controller.
The function corresponds to serial command ':port_in_b'.

很遗憾,它没有描述InputSelection 的实际含义。

【讨论】:

  • 感谢您抽出宝贵时间,雷米!为 IDispatch 调用 QueryInterface 不会崩溃,但也不会成功。我还尝试了Supports(GetInput1Selection,TDispatch),它返回 FALSE。似乎不支持 IDispatch。我还有哪些选择?
  • 更准确地说,QueryInterface(GetInput1Selection,IDispatch) 返回E_NOINTERFACE
  • 那你需要联系SDK厂商询问一下。 QueryInterface() 返回 E_NOINTERFACE 而没有崩溃的事实意味着 GetInput1Selection() 实际上返回了一个有效的 IUknown 接口,这意味着文档是错误的,或者至少是误导性的。您确定在导入的 TypeLibrary 中没有声明其他接口类型吗?
  • 可悲的是,供应商在这里没有帮助(见我上面的评论)。但我采用了蛮力方法,找到了一个兼容的接口:IProvideClassInfo,它提供了对ITypeInfo 接口的访问。这可能有用吗?我在这里超出了我的深度。非常感谢您对此的任何进一步帮助!
  • 是的,控制 NanoTec 步进电机接口正是我正在做的事情。你是对的,文档很差。但是关于IProvideClassInfo,我不知道该怎么办。我对它的ITypeInfo 接口进行了一些处理,这将我带到了mscorlib.dll 的类型库。这里声明了一个_Object接口,我神秘的IUnknown也支持。不过,我不知道这是否有任何意义。
猜你喜欢
  • 2011-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-11
  • 2012-09-11
  • 2015-10-13
  • 1970-01-01
  • 2013-06-07
相关资源
最近更新 更多