以下代码工作正常,非常感谢您使用一个COM客户端,但是使用新客户端(相同软件的更新版本)string_array_to_bstr_safearray_variant
会引发访问冲突并且一切都会死亡。
任何人都可以告诉我,如果我做错了,我之前就已经逃脱了......?我没有正确分配内存吗?
#include "comutil.h"
void string_array_to_bstr_safearray_variant(long arraylength,char ** in_array,VARIANT *out_variant)
{
CComSafeArray<BSTR> out_array;
ATLENSURE_SUCCEEDED(out_array.Create(arraylength));
for (int i=0;i<arraylength;i++)
ATLENSURE_SUCCEEDED(out_array.SetAt(i,_com_util::ConvertStringToBSTR(in_array[i])));
CComVariant ccv(out_array);
HRESULT hr = ccv.Detach(out_variant);
ATLENSURE_SUCCEEDED(hr);
}
//names: output parameter to contain variant holding safearray of bstrs
STDMETHODIMP CCalculation::get_output_shortnames(VARIANT* names)
{
char** names_array = calc_get_short_output_names(calc); //this works fine
string_array_to_bstr_safearray_variant(output_length,names_array,names); //this fails before returning
return S_OK;
}
修改:调试程序信息
如果没有调试器,我会收到访问冲突。
使用调试器逐步执行此代码似乎可行。 output_length
设置正确; out_array
已正确创建并填充,因此我可以通过变量观看来out_variant
。但是,COM客户端仍然失败,说"lisp value has no coercion to VARIANT with this type: #<safearray...>"
(这很奇怪,因为客户端的先前版本很好地解释了返回值)。它然后崩溃抱怨它是内存不足。
在调试器中运行代码,但是让它运行而不是步进,它在CComVariant
的构造函数内部失败,抱怨因为对SafeArrayCopy
的内部调用失败而抛出了无效的参数。
编辑:在最近的另一个步骤中它在循环中失败了,所以问题可能是CComSafeArray,因为@terriblememory建议?
答案 0 :(得分:1)
CComSafeArray的文档实际上并不表示它支持BSTR。 BSTR的功能标志是否在底层SAFEARRAY中设置? (这不是一个真正的答案,但我没有业力只是评论,抱歉!)
答案 1 :(得分:1)
最后我找到了答案!问题中张贴的代码是正确的。早期的代码导致了未定义的行为:
STDMETHODIMP CCalculation::configure(VARIANT radii) // radii contains a safearray of doubles
{
CComSafeArray<double> radii_sa;
radii_sa.Attach(radii.parray);
ULONG num_radii = radii_sa.GetCount();
//unpack radii array into c-style array
double *radii_array = new double[num_radii];
for (long i=0;i<num_radii;i++)
radii_array[i] = radii_sa.GetAt(i);
//...do something with radii_array...
delete[] radii_array;
return S_OK;
}
你是否发现了故意的错误? COM规则说半径由客户端拥有,而不是我的dll。通过附加到它然后让包装超出范围,我正在释放safearray。通过在return语句之前添加它来修复:
radii_sa.Detach();