简化案例:我需要通过现有的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的,它需要在同一个环境中的单个机器上进行跨进程处理。
答案 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>