JS与C++交互方法汇总

本文详细阐述了如何利用回调函数在C++与脚本语言之间实现高效交互,包括设置回调函数、测试回调功能及解析脚本语言自定义类型的实现过程。通过示例代码展示具体应用,强调了回调函数方法的灵活性和通用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大家都知道通过Idispatch接口可使C++与动态语言交互, 本文分别列出各种交互方法,并着重讲解我说喜欢的一种方法,希望给网友们一些帮助,同时欢迎大家推敲和讨论

1、连接点事件,此法请参考vckbase杨老师博客

2、事件和通知,参考vckbase杨老师博客

上述两法的弊端在于:客户必须实现一个接收器,对于不同的语言实现接收器的方式各不同,如js接收器必须用特定的html标签标识出来,且只能是嵌入在html文档里面,不适和单独的js脚本,此法使用如下:

<script   language= "javascript "   for= "window "   event= "onload ">

也可下载示例代码看看每种接收器的具体实现:atl连接点、c++接收器、js接收器


总之,使用连接点有太多不便,主要是不灵活,我不大喜欢,其实,只要想一下,既然js可以调用我的c++函数, 说明js可以认识c++函数,那么我的c++函数一定能通过相逆的方式认识JS函数, 也许直接通过回调函数即可完成, 没错, 下面我要讲的就是回调函数。


3、回调函数。此法的强大之处在于,主要你能调用我的C++函数, 我就能调用你给的回调函数, 此法的好处:简单、通用。

上代码:

新建一个ATL工程, 添加ATL简单对象CB,给CB添加接口SetCallBack、Test、Test1


// CB.cpp : CCB 的实现

#include "stdafx.h"
#include "CB.h"
#include <atlstr.h>
#include <dispex.h>


// CCB
IDispatch* s_spCallback;//手动添加, 用来保存js传过来的回调函数

STDMETHODIMP CCB::SetCallBack(VARIANT scriptcb)
{
	// TODO: 在此添加实现代码
	if (scriptcb.vt == VT_DISPATCH)
    {
        s_spCallback = scriptcb.pdispVal;
    }
	return S_OK;
}

STDMETHODIMP CCB::Test(LONG l) //测试回调函数
{
	// TODO: 在此添加实现代码
	CComVariant avarParams[1];
    avarParams[0] = l; //指定回调函数的参数
    DISPPARAMS params = { avarParams, NULL, 1, 0 };
    if(s_spCallback)
    {
        HRESULT hr = s_spCallback->Invoke(0, 
            IID_NULL, 
            LOCALE_USER_DEFAULT, 
            DISPATCH_METHOD, 
            ¶ms, NULL, NULL, NULL);
    }
	return S_OK;
}

STDMETHODIMP CCB::Test1(VARIANT v)
{
	// TODO: 在此添加实现代码
	//CString str;
	//str.Format(_T("%d"), v.vt);
	//::MessageBox(NULL, str, _T(""), 0);

	
	CComQIPtr<IDispatchEx> pParamEx = v.pdispVal;
	if( !pParamEx )
		return S_OK;

	DISPID dispid;
	DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};

	HRESULT hr = pParamEx->GetNextDispID(fdexEnumAll, DISPID_STARTENUM, &dispid);
	while (hr == NOERROR)
	{
		BSTR bstrName = NULL;
		VARIANT var;
		hr = pParamEx->GetMemberName(dispid, &bstrName);
		 pParamEx->InvokeEx(dispid, LOCALE_USER_DEFAULT,
         DISPATCH_PROPERTYGET, &dispparamsNoArgs, 
         &var, NULL, NULL);
		 ::MessageBox(NULL, var.bstrVal, _T(""), 0);
		SysFreeString(bstrName);

		hr = pParamEx->GetNextDispID(fdexEnumAll, dispid, &dispid);
	}

	return S_OK;
}




新建一个js脚本:

function callback(i)
{
  WScript.echo(i);
}
var obj = new ActiveXObject("TestJsCallBack.CB");
//var obj = new ActiveXObject("TestJsCallBack.CB.1")
obj.SetCallBack(callback)
obj.Test(456)//测试回调函数
var para = {"111":"111value","222":"222value"};
obj.Test1(para)//测试C++解析json对象



注:使用IDispatchEx接口:
在自定义类中添加头文件
#include "dispex.h"
在idl文件中 包含IDL文件

import "dispex.idl";


其实两种语言的交互无非要完成以下功能:1、能相互调用对方函数

2、能相互识别对方的自定义类型

从上述的Test1函数看出使用IdispatchEx可以解析js传给C++的自定义类型, 而js里面的这句话var obj = new ActiveXObject("TestJsCallBack.CB");告诉我们, C++将一个类暴露给了js


综上所述,IDiptch是不仅可以将C++接口暴露给脚本语言, 还可以解析脚本语言的函数或者对象, 实现二者相互调用






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值