我有一个实现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指示调用者拥有输出参数。