我有一个实现IDispatch接口(interface)的类(JSObject)。该类公开了在托管Web浏览器控件(IWebBrowser2)中运行的JavaScript。

在此处查看有关其工作原理的更多信息:Calling C++ function from JavaScript script running in a web browser control

我可以从我的JavaScript代码中调用JSObject,并且可以接收返回的整数/整数。但是当函数返回字符串(BSTR)时出了点问题。

这是IDispatch::Invoke()代码的一部分:

int lenW = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, "Returned string", -1,
    NULL, 0);
BSTR bstrRet = SysAllocStringLen(0, lenW);
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, "Returned string", -1, bstrRet,
    lenW);

pVarResult->vt = VT_BSTR;
pVarResult->bstrVal = bstrRet;

// Who calls SysFreeString(bstrRet);?

使用上面的代码,您可以alert()返回的字符串,但是不能添加它。 alert(returnedString + "foo");将仅显示“返回的字符串”。 “foo”部分未添加到字符串中。字符串的末尾似乎出了点问题。有任何想法吗?

另外,由于我没有调用SysFreeString(),我是否在这里泄漏内存?

编辑:

我暂时包含了atlbase.h,因此可以使用CComBSTR。上面的代码现在看起来像这样:
pVarResult->vt = VT_BSTR;
pVarResult->bstrVal = CComBSTR("test string");

逐步执行该代码肯定会显示pVarResult一直是“测试字符串”,直到函数返回为止。但是,当我用我的JavaScript代码中的alert()返回的字符串时,我得到了“扩展”。 alert(returnedString + "foo")是“expandedfoo”。因此,这是朝正确方向迈出的一小步,因为您可以添加到返回的字符串中。但这也是错误的方向,因为返回的字符串不是我真正返回的字符串...
*pVarResult = CComVariant("test string");

该代码给出的结果与上一个 list 中的代码相同(使用CComBSTR)。

最佳答案

第一个MultiByteToWideChar()调用返回存储字符串所需的字符数,包括空终止符。然后SysAllocStringLen()lenW+1字符分配了一个缓冲区(多于一个所需的字符),并且已经以null终止。

由于MultiByteToWideChar()还写了一个空终止符,因此您在字符串末尾以两个结尾。对于BSTR,可以使用嵌入的空字符,因为它们的长度是前缀,因此JScript实现可能会串联而不会删除其他的...因此,您最终得到的字符串是中间带有嵌入的空字符的字符串,该字符串仅会被打印部分地。

长话短说,固定长度:

lenW = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, NULL, 0);
bstrRet = SysAllocStringLen(0, lenW-1);
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, bstrRet, lenW-1);

如注释中所述,字符串将由调用方释放-memory management rules指示调用者拥有输出参数。

10-08 08:22
查看更多