从C ++函数将字符串返回到JavaScript [英] Returning string to JavaScript from C++ function

查看:201
本文介绍了从C ++函数将字符串返回到JavaScript的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



在此处了解如何工作:从Web浏览器控件中运行的JavaScript脚本调用C ++函数

我可以从我的JavaScript代码调用JSObject,并且我可以接收返回的整数/长整型。但是当函数返回一个字符串(BSTR)时出现错误。



这是 IDispatch :: Invoke c $ c> code:

  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;

//谁调用SysFreeString(bstrRet);?

使用上面的代码,您可以 alert()返回的字符串,但是你不能添加它。 alert(returnedString +foo); 将只显示返回的字符串。 foo部分不会添加到字符串。似乎有一些问题,字符串的结束不知何故。任何想法任何人吗?



此外,我在这里泄漏记忆,因为我不调用 SysFreeString()



EDIT:



我暂时包含atlbase.h, c $ c> CComBSTR 。上面的代码现在看起来像这样:

  pVarResult-> vt = VT_BSTR; 
pVarResult-> bstrVal = CComBSTR(test string);

通过该代码可以看出pVarResult一直是test string,直到函数返回。但是当我alert()返回的字符串在我的JavaScript代码,我得到扩展。 alert(returnedString +foo)是expandedfoo。所以它是一个正确的方向上的一小步,你可以添加到返回的字符串。但是它也是一个错误的方向,因为返回的字符串不是我真正返回的...

  * pVarResult = CComVariant(test string); 

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

解决方案

第一个 MultiByteToWideChar()调用返回存储字符串,包括null终止符。然后 SysAllocStringLen() lenW + 1 字符(一个超过所需)分配一个缓冲区, 。



由于 MultiByteToWideChar()也写了一个null终止符,串。对于 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);

如注释中所述,字符串将被调用者释放 - 内存管理规则规定out-parameters由调用者拥有。


I have a class (JSObject) that implements the IDispatch interface. The class is exposed to JavaScript running in my hosted web browser control (IWebBrowser2).

See more here about how this works: Calling C++ function from JavaScript script running in a web browser control

I can call in to JSObject from my JavaScript code, and I can receive returned integers/longs. But something goes wrong when the function returns a string (BSTR).

This is a part of the IDispatch::Invoke() code:

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);?

With the above code you can alert() the returned string, but you can not add to it. alert(returnedString + "foo"); will only show "Returned string". The "foo" part is not added to the string. There seems to be something wrong with the end of the string somehow. Any ideas anyone?

Also, am I leaking memory here since I'm not calling SysFreeString()?

EDIT:

I temporarily included atlbase.h so I could use CComBSTR. The above code now looks like this:

pVarResult->vt = VT_BSTR;
pVarResult->bstrVal = CComBSTR("test string");

Stepping through that code definitely shows that pVarResult is "test string" all the way until the function returns. But when I alert() the returned string in my JavaScript code I get "expanded". alert(returnedString + "foo") is "expandedfoo". So it is a small step in the right direction as you can add to the returned string. But it's also a step in the wrong direction as the returned string isn't what I really returned...

*pVarResult = CComVariant("test string");

That code gives the same results as the code in the previous listing (using CComBSTR).

解决方案

The first MultiByteToWideChar() call returns the amount of characters needed to store the string, including the null-terminator. Then SysAllocStringLen() allocates a buffer for lenW+1 characters (one more than needed) and already null-terminates it.

As the MultiByteToWideChar() also writes a null-terminator, you end up with two at the end of the string. For BSTRs embedded null-characters are possible as they are length prefixed, so the JScript implementation probably concatenates without removing the additional one... thus you end up with a string with an embedded null-character in the middle which will only be printed partially.

Long story short, fix the lengths:

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);

As mentioned in the comment, the string is to be freed by the caller - the memory management rules dictate that out-parameters are owned by the caller.

这篇关于从C ++函数将字符串返回到JavaScript的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆