我必须编写一个由插件接口调用的COM服务器DLL(使用ATL) 一个旧的(闭源)VB6应用程序,并希望避免 可能的泄漏(当然)!接口描述按原样给出,不能 不幸的是改变了:
将在VB端声明要调用的类方法,如下所示:
Public Function Process(data As Object,
Params As Variant,
Results() As Single) As Integer
IDL中的接口声明如下:
[id(1)] HRESULT Process([in,out] IDispatch** pDataIDisp,
[in,out] VARIANT* pParamsVar,
[in,out] SAFEARRAY(FLOAT)* pResSA,
[out,retval] SHORT* pRetVal);
最后调用的代码如下所示:
STDMETHODIMP Analyzer::Process(IDispatch** pDataIDisp,
VARIANT* pParamsVar,
SAFEARRAY** pResSA,
SHORT* pRetVal)
{
try
{
// Prepare for access
CComPtr<IDispatch> dataComPtr = *pDataIDisp;
// VARTYPE from caller is VT_VARIANT | VT_ARRAY | VT_BYREF;
CComVariant prms = *pParamsVar; // OR use .Attach ?
CComSafeArray<VARIANT> prmsArr = prms.parray; // OR use prms.Attach ?
// SafeArray is FADF_HAVEVARTYPE
CComSafeArray<FLOAT> res = *pResSA; // OR use res.Attach(pResSA*) ?
{
// Use ATL types wrapped from above
}
// Cleanup ????
.
.
.
}
catch (...) {}
return S_OK;
}
我想知道的是:
我的接受(和转换)参数的方法是ATL 键入正确的用法还是有另一种(更好的?)方式?
我是否必须在IDispatch *上自行调用AddRef()和/或Release()或 是否足以分配给CComPtr来完成这一切?
作为VT_BYREF给出的第二个参数的含义是什么?
头文件说:
* VT_VARIANT [V][T][P][S] VARIANT *
* VT_ARRAY [V] SAFEARRAY*
* VT_BYREF [V] void* for local use
我不清楚......#-o
在存储的SAFEARRAY上使用SafeArray(Un)AccessData就足够了 VARIANT(第二个参数)?
要使这件事能正常运行(强健)还需要考虑哪些其他事项?
感谢您抽出宝贵时间并帮助我!
ps:我已经开始工作(或多或少)我只想避免问题(泄漏!) 我不能 调试,因为调用应用程序是封闭源代码而不是我的控制......
答案 0 :(得分:1)
你正在使用安全数组和输入/输出参数使你真正的编译。特别是与古老的VB6结合使用时,您将接口。
有一些简单的规则可以使其清晰,简单和可靠:
[in]
,[out]
,[out, retval]
个参数;在你的代码片段中,你使用[in, out]
而没有任何显示的意图来实际更改值以利用out说明符:当你没有特殊的理由时,它只会使C ++方面变得复杂,并且额外的引用级别增加了错误ByRef
,参数将由ByVal
你会这样:
[id(1)] HRESULT Process([in] IDispatch* pDataIDisp,
[in] VARIANT pParamsVar,
[out, retval] VARIANT* pvResult);
在C ++服务器端,您只能读取参数,不需要释放。您将使用ATL CComVariant
和朋友在C ++中完全构建它来初始化输出变量,然后在处理的最后阶段将其分离。
Public Function Process(data As Object,
Params As Variant) As Object
' ...
Dim Data, Params As Object
' ...
Dim Result As Object
Result = Server.Process(Data, Params)
' NOTE: Result is OK to be an array