跨进程COM Marshaler:减少大型阵列的副本数量

时间:2014-01-31 13:32:58

标签: c++ windows com marshalling

简化案例:我需要通过现有的COM接口将VARIANT传输到另一个进程。我目前使用MIDL生成的编组器。

实际转移是针对许多值的,是时间关键过程的一部分,可能涉及大字符串或safearray(几MB),因此制作的副本数量似乎相关。

由于接收器需要将数据“保留”在函数调用之外,因此编组器需要至少复制一个副本。然而,我能想到的所有签名都包含两个副本:

SetValue([in] VARIANT)
GetValue([out] VARIANT *)  // called by receiver

在这两种情况下,根据我的理解,编组程序会制作一个跨进程的副本,它会被编组器破坏。由于我需要将数据保存在接收器中,我需要制作第二个副本。

我考虑在接收方“分离”数据:

SetValue([in, out] VARIANT *)  
    // receiver detaches value and sets to VT_EMPTY for return

但这也会破坏消息来源。

Q1:是否可以让MIDL生成的封送代码只进行一次复制?
Q2:使用自定义编组器是否可以实现这一目标,代价是什么? (我的第一次调查极度令人沮丧)

我非常喜欢使用SAFEARRAY和/或其他VARIANT / PROPVARIANT类型,并传输整个数组。

[edit]

双方都使用C ++,接口是基于IUnknown的,它需要在同一个环境中的单个机器上进行跨进程处理。

1 个答案:

答案 0 :(得分:0)

你没有这么明确地说,但你想要解决的问题似乎是速度问题。在任何情况下,如果您还没有这样做,请考虑使用分析器来识别瓶颈

在这种情况下,我非常怀疑这是花费时间的复制。相反,它可能是所涉及的过程之间的上下文切换,因为您一次获得一个值。这意味着对于您检索的每个值,您必须将进程切换到调用的目标,然后再切换回来。

在设置或获取多个值时,您可以极大地提高设计速度。

这样的事情:

SetMultipleValues(
[in] SAFEARRAY(BSTR)* asNames,
[in] SAFEARRAY(VARIANT)* avValues
)

GetMultipleValues(
[in] SAFEARRAY(BSTR)* asNames,
[out,retval] SAFEARRAY(VARIANT)* pavValues
)

即。在调用GetMultipleValues时,传入一个包含10个名字的数组,并按照传入的名称接收一个包含10个值的数组,(如果该值不存在,则为VT_EMPTY。) p>