Com [in]参数能否用于返回数据?

Com [in]参数能否用于返回数据?,com,Com,我不太清楚[in]和[out]如何与传递值和传递引用概念交互。MSDN文档明确指出,[in]表示数据从调用者流向被调用者,数据从被调用者流向调用者需要[out] 然而,有人建议我对调用方可以检索结果的对象使用[in]参数 IDL中的方法定义示例: HRESULT _stdcall a_method( [in] long *arg1, [in] BSTR arg2, [in] IAnObject *arg3 ); 在我的服务器实现此方法时(使用C++),我可以编写: *arg1 = 20; ar

我不太清楚
[in]
[out]
如何与传递值和传递引用概念交互。MSDN文档明确指出,
[in]
表示数据从调用者流向被调用者,数据从被调用者流向调用者需要
[out]

然而,有人建议我对调用方可以检索结果的对象使用
[in]
参数

IDL中的方法定义示例:

HRESULT _stdcall a_method( [in] long *arg1, [in] BSTR arg2, [in] IAnObject *arg3 );
在我的服务器实现此方法时(使用C++),我可以编写:

*arg1 = 20;
arg2[0] = L'X';    // after checking length of string is not 0
arg3->set_value(50);
在客户端代码中,使用C++:

long val1 = 10;
BSTR val2 = SysAllocString(L"hello");
IAnObject *val3 = AnObject_Factory::Create();  

ptr->a_method(&val1, val2, val3);
当我尝试此操作时(通过进程内服务器使用我的对象),服务器的所有三个更改都被传播到客户端,即
val1==20
val2
“Xello”
,以及
val3->get_value()
get
50

我的问题是:这种行为是否有保证,即如果我对另一台机器使用进程外服务器或DCOM,它是否会在
val1
val2
val3
中看到相同的更改

我以前认为,
[in]
向底层RPC指示参数只需在一个方向上封送;它不必尝试将更改发送回调用方。但现在我不太确定


我希望我的对象是自动化兼容的(即可从VB6、Java等中使用-无需自定义封送),并且它应该能够通过DCOM而不是进程中使用,而不需要对客户端代码进行任何更改。

您不应该更改
[in]
参数的内容,因此,以下代码是错误的:

*arg1 = 20;
arg2[0] = L'X';    // after checking length of string is not 0
您看到的变化是反映出来的,因为您在同一个公寓打电话,而在那里没有进行封送处理。返回值的正确方法是使用
[out]
[in,out]
参数

但是,您可以访问其内容并调用其方法(对于接口指针),因此以下代码是正确的:

arg3->set_value(50);

编辑:进一步回答您的问题

封送处理可以以两种方式进行,并且
[in]
[out]
属性会指示方式


对于自动化,我建议您不要返回超过典型的
[out,retval]
参数的值来支持脚本语言。如果必须返回多个值,请返回带有属性的
IDispatch
。如果你认真对待脚本化自动化,那么可以把它作为一个很好的起点。

为了扩展@Paulo madeira的答案,我可以保证,如果涉及代理,那么

*arg1 = 20;
arg2[0] = L'X';    // after checking length of string is not 0

充其量将被忽略,最坏情况下将损坏堆。

使用
[in,put]
,而不是
[in]
[in,out]
参数包含调用前和调用后的值。封送拆收器将双向发送值。注意:您无法通过尝试在与调用者相同的单元上运行进程内服务器来证明属性的任何内容(IDL属性对调用没有影响,因为它是直接调用,绕过了封送拆收器)。那么必须是
[in,out]IAnObject**arg4
?其中
arg3->设置_值(50)“go”,如果它只是
[in]
,或者这违反了规范?确定。因此,客户端可以调用
val3->AddRef()事先,然后
val3->get_value()
之后?但可能会让其他不希望出现这种行为的开发人员感到困惑?对不起,我的第一条评论没有回答您的问题。您可以使用
[in,out]
双向传递值。您正在尝试使用对象传入和传出值。除非您希望被调用方传回一个新对象,否则您应该使用
[in]
作为对象指针,就像您被告知的那样。抱歉搞混了。好的。对于
arg1
(对于进程外或DCOM),发生的情况是在存根(服务器)中创建
long
,该存根由代理(客户端)封送的值初始化,并且服务器中的
arg1
指向存根;因此,即使服务器修改了
*arg1
,它也不会被封送回客户端,因为它是
[in]
。但是,使用
arg3
,调用
arg3->set_value()
不会在存根中设置值,它会对居住在客户端公寓中的对象进行另一个跨进程调用。因此,客户机看到了这个值。我想这些碎片现在已经就位了!