2013-05-12 31 views
3

我正在为应用程序实现COM自动化(双接口)。自动化界面将从VBScript调用。我不清楚该方法的参数允许使用哪些类型。我知道基本值必须符合VARIANT,但是这是否意味着所有类型为int的参数都必须通过VARIANT,或者可以直接通过int在COM自动化接口中允许“输出”参数类型

例如,两种方法我在MIDL文件是:

HRESULT SetDate([in] int Year, [in] int Month, [in] int Day); 
HRESULT GetDate([out] int* pYear, [out] int* pMonth, [out] int* pDay); 

调用SetDate从VBScript工作。如图所示调用GetDate失败,也就是说,在C++的实现中,ITypeInfo::Invoke返回一个指示类型错误的代码。

我观察到,如果使用VARIANT而不是int,如下所示,它可以工作。

HRESULT GetDate([out] VARIANT* pYear, [out] VARIANT* pMonth, [out] VARIANT* pDay); 

所以是int不允许参数(因为双界面),或者我必须做别的事情了?如果不允许int,为什么SetDate工作 - 在这方面的输入参数和输出参数之间是否存在差异?

此外,这对方法的工作原理,虽然两者使用int

[propget] HRESULT System([out, retval] int* pSystem); 
[propput] HRESULT System([in] int System); 

为什么 - 是规则的属性不同的允许的参数类型,或当参数被声明为retval

我不太明白这一切 - 如果有人能澄清这一点,将不胜感激。

回答

2

显然,当您通过IDispatch调用接口时,所有参数总是以VARIANT s的形式传递。然而,你的实现可能使用其他类型。差距如何弥合?

ATL(假设这就是你正在使用的)将为你实现Invoke,代码将参数从VARIANT s转换为您的方法签名使用的正确类型,然后将调用转发给实际方法。

下面是规则:

  • [in]参数可以只是适合在VARIANT任何类型的,因为你发现了。 ATL(或任何您正在使用的库)将为您处理翻译参数。

  • [in, out]参数必须是VARIANT*。如果您使用其他任何方法,则调用将不起作用或返回值将丢失(我不记得它是以哪种方式进行的;您表示此时出现运行时错误)。当你的方法返回时,ATL会将参数转换为适当的VARIANT,以便VBScript(或任何IDispatch客户端发起的调用)可以获得输出值。

  • [retval, out]是一种特殊情况。您可以使用指向您选择的任何类型的指针,ATL将负责处理它。我认为这是可能的,返回值是在DISPPARAMS机制之外提供的。

  • [out] ...只是不。它们不起作用 - VBScript无法正确使用[out]参数。请注意,他们将“工作”,因为该方法将无误地执行,但VBScript无法区分[out][in, out],这意味着VBScript希望您的方法在接收到参数时释放参数的任何值。如果您使用[out],则无论在进行方法调用之前放置在参数上的客户端代码是否永久泄露。

+0

感谢您的答复。我没有使用ATL,只是简单的C++。如果我将[out]改为[out,ref],是否应该起作用? – Dabbler 2013-05-13 05:47:50

+0

你真的在实现你自己的'Invoke'吗?这是一个重要的细节;你应该加上这个问题。原则上,您可以编写一个'Invoke'的实现,它接受vbscript提供的'VARIANT'并将其转换为您的方法的int *'(如果可以,或者返回错误,否则返回)。然后,您的调用将负责获取参数的返回值,并将其填充到脚本客户端提供的参数(如果可以,或者如果不可以,则放弃它)。这是一项不重要的工作量 - 客户可以向您传递任何信息,并且您需要为此做好准备。 – 2013-05-13 22:39:51

+0

注意:当我打算说'[in,out]'时,我的文章的早期版本使用'[ref]' - 一个愚蠢的滑倒。 – 2013-05-13 22:54:24

1

有涉及您的问题两种不同的技术:

  • COM自动化,至极的发展围绕IDispatch接口和朋友(尤其是受限制的类型系统,并不需要特定的封送处理代码,因为OLEAUT在获取TLB时自动执行作业)
  • VBScript,它是一个特定的COM自动化客户端。

out或in/out不是VARIANT的参数对于COM自动化来说一般都适用,但VBScript不适用,因为VBScript基本上只知道VARIANT。

你会发现埃里克利珀的BLOB这里明确的解释:In, Out, In-Out, Make Up Your Mind Already

2

类型,你将不得不在Windows SDK都列在VT_xxx枚举的顶部较小的烦恼:

enum VARENUM 
    { VT_EMPTY = 0, 
    VT_NULL = 1, 
    VT_I2 = 2, 
    VT_I4 = 3, 
    VT_R4 = 4, 
    VT_R8 = 5, 
    VT_CY = 6, 
    VT_DATE = 7, 
    VT_BSTR = 8, 
    VT_DISPATCH = 9, 
    VT_ERROR = 10, 
    VT_BOOL = 11, 
    VT_VARIANT = 12, 
    VT_UNKNOWN = 13, 
    VT_DECIMAL = 14, 
    VT_I1 = 16, 
    VT_UI1 = 17, 

你不你看不到INT,是吗? LONG改为(这是VT_I4)将工作得很好,并在各地得到很好的支持。

对于脚本编写环境,您最好使用VARIANT s,如果这样可以让您在C++方面更轻松 - 使用上面提到的简单类型。如果你需要一个数组,VARIANT对他们来说也是一个好的持有者。

一个不错的桌子上有也有预兆的类型兼容性:

/* 
* VARENUM usage key, 
* 
* * [V] - may appear in a VARIANT 
* * [T] - may appear in a TYPEDESC 
* * [P] - may appear in an OLE property set 
* * [S] - may appear in a Safe Array 
* 
* 
* VT_EMPTY   [V] [P]  nothing 
* VT_NULL    [V] [P]  SQL style Null 
* VT_I2    [V][T][P][S] 2 byte signed int 
* VT_I4    [V][T][P][S] 4 byte signed int 
* VT_R4    [V][T][P][S] 4 byte real 
* VT_R8    [V][T][P][S] 8 byte real 
* VT_CY    [V][T][P][S] currency 
* VT_DATE    [V][T][P][S] date 
* VT_BSTR    [V][T][P][S] OLE Automation string 
* VT_DISPATCH   [V][T] [S] IDispatch * 
* VT_ERROR   [V][T][P][S] SCODE 
* VT_BOOL    [V][T][P][S] True=-1, False=0 
* VT_VARIANT   [V][T][P][S] VARIANT * 
* VT_UNKNOWN   [V][T] [S] IUnknown * 
* VT_DECIMAL   [V][T] [S] 16 byte fixed point 
* VT_RECORD   [V] [P][S] user defined type 
* VT_I1    [V][T][P][s] signed char 
* VT_UI1    [V][T][P][S] unsigned char 
* VT_UI2    [V][T][P][S] unsigned short 
* VT_UI4    [V][T][P][S] unsigned long 
* VT_I8     [T][P]  signed 64-bit int 
* VT_UI8     [T][P]  unsigned 64-bit int 
* VT_INT    [V][T][P][S] signed machine int 
* VT_UINT    [V][T] [S] unsigned machine int 
* VT_INT_PTR    [T]  signed machine register size width 
* VT_UINT_PTR   [T]  unsigned machine register size width 
* VT_VOID    [T]  C style void 
* VT_HRESULT    [T]  Standard return type 
* VT_PTR     [T]  pointer type 
* VT_SAFEARRAY   [T]  (use VT_ARRAY in VARIANT) 
* VT_CARRAY    [T]  C style array 
* VT_USERDEFINED   [T]  user defined type 
* VT_LPSTR    [T][P]  null terminated string 
* VT_LPWSTR    [T][P]  wide null terminated string 
* VT_FILETIME    [P]  FILETIME 
* VT_BLOB     [P]  Length prefixed bytes 
* VT_STREAM     [P]  Name of the stream follows 
* VT_STORAGE    [P]  Name of the storage follows 
* VT_STREAMED_OBJECT  [P]  Stream contains an object 
* VT_STORED_OBJECT   [P]  Storage contains an object 
* VT_VERSIONED_STREAM  [P]  Stream with a GUID version 
* VT_BLOB_OBJECT   [P]  Blob contains an object 
* VT_CF      [P]  Clipboard format 
* VT_CLSID     [P]  A Class ID 
* VT_VECTOR     [P]  simple counted array 
* VT_ARRAY   [V]   SAFEARRAY* 
* VT_BYREF   [V]   void* for local use 
* VT_BSTR_BLOB      Reserved for system use 
*/