Posted on 2009-09-14 15:01
S.l.e!ep.¢% 阅读(1555)
评论(1) 编辑 收藏 引用 所属分类:
COM
为了实验,写了一个COM组件嵌入HTML,大概功能是接收服务器的数据,并显示出来
HTML 调用COM组件的代码大概是这样的:
<html>
<SCRIPT LANGUAGE="JavaScript">
<!--
function onRecvData()
{
try
{
var obj_Connection = new ActiveXObject("MyObj.MyObj.1");
obj_Connection.OnRecv = function onRecv(buf, len)
{
testbox.value = buf;
} ;
obj_Connection.init(12345);
}
catch(e)
{
var strErrMsg;
strErrMsg = "Error: " + e.message;
alert(strErrMsg);
}
}
//-->
</SCRIPT>
</HEAD>
<BODY>
<input onClick="onRecvData();" type="button" value="Go">
<input type="text" id = testbox>
</BODY>
</html>
COM组件在接收到SOCKET的数据之后,就会调用
void CMyObj::onReceive(const char* pData, int nLen)
{
if ( m_pfnRecv != NULL )
{
CComVariant* pvars = new CComVariant[2];
pvars[1] = pData;
pvars[0] = nLen;
DISPPARAMS disp = { pvars, NULL, 2, 0 };
HRESULT hr = m_pfnRecv->Invoke(0, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
delete[] pvars;
}// if ( m_pfnRecv != NULL )
}
其中的 m_pfnRecv 就是通过 STDMETHODIMP CMyObj::put_OnRecv(IDispatch *newVal) 的方法设置进去的
发现在调用几十次(大约80次左右后),COM组件会出错(访问的地址不可读),出错堆栈大约如下:
First-chance exception in IEXPLORE.EXE (JSCRIPT.DLL): 0xC0000005: Access Violation.
JSCRIPT! 75bc4a27()
JSCRIPT! 75bc7564()
JSCRIPT! 75bc7414()
JSCRIPT! 75bc678e()
CMyObj::onReceive(const char * 0x0012e40c, int 260) line 64 + 44 bytes
想了很久,没想出好的解决方法,一直在怀疑是否是 m_pfnRecv->Invoke 调用的问题
于是乎做了以下的实验:
将HTML调用COM组件的代码改为:
<html>
<SCRIPT LANGUAGE="JavaScript">
<!--
function onRecv(buf, len)
{
testbox.value = buf;
} ;
function onRecvData()
{
try
{
var obj_Connection = new ActiveXObject("MyObj.MyObj.1");
obj_Connection.OnRecv = onRecv;
obj_Connection.init(12345);
}
catch(e)
{
var strErrMsg;
strErrMsg = "Error: " + e.message;
alert(strErrMsg);
}
}
//-->
</SCRIPT>
</HEAD>
<BODY>
<input onClick="onRecvData();" type="button" value="Go">
<input type="text" id = testbox>
</BODY>
</html>
改完之后,又发现另一问题
在调用几十次之后,它会走到 CMyObj 的析构
~CMyObj()
{
}
每次点击 Go 按钮, 它都会执行几十次后,就析构
于是乎,再改了下HTML ,将 obj_Connection 改为全局变量
<html>
<SCRIPT LANGUAGE="JavaScript">
<!--
var var obj_Connection;
function onRecv(buf, len)
{
testbox.value = buf;
} ;
function onRecvData()
{
try
{
obj_Connection = new ActiveXObject("MyObj.MyObj.1");
obj_Connection.OnRecv = onRecv;
obj_Connection.init(12345);
}
catch(e)
{
var strErrMsg;
strErrMsg = "Error: " + e.message;
alert(strErrMsg);
}
}
//-->
</SCRIPT>
</HEAD>
<BODY>
<input onClick="onRecvData();" type="button" value="Go">
<input type="text" id = testbox>
</BODY>
</html>
这下终于正常了,只有每当按 F5去刷新页面的时候,才会调用到 MyObj 的析构
需要再细究下原因。