XPCOM的JS回调(VS2010)
站长推荐:NSetup一键部署软件
一键式完成美化安装包制作,自动增量升级,数据统计,数字签名。应对各种复杂场景,脚本模块化拆分,常规复杂的脚本代码,图形化设置。无需专业的研发经验,轻松完成项目部署。(www.nsetup.cn)
1.XPCOM的很多东西都和COM的内容很像。当然也就在类型上有很多麻烦的地方,在此也不再啰嗦,读者自己研究尝试。
这里只是做个简单的示例,用于XPCOM回调JS内容。
准备:
1.下载python2.7.3(高的版本貌似有点问题,木有深入研究过),并设置环境变量,网上很多,不再说。(加入ClassPath中即可)
2.在cmd下输入python+回车,出现下图,表示成功
3.下载xulrunner-sdk.zip。
4.建立模板工程。下载setup.js,进入setup.js目录,在cmd下,setup.js回车即可安装。setup.js代码如下。(注意暂时此setup.js只支持VS2010)
setup.js的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
main(); function main() { var debug = false; // Create shell object var shell = WScript.CreateObject("WScript.Shell"); var fso = WScript.CreateObject("Scripting.FileSystemObject"); // 当前目录 var strCurrentDir = ""; if (WScript.ScriptFullName.lastIndexOf("\\") != -1) { strCurrentDir = WScript.ScriptFullName.substring(0, WScript.ScriptFullName.lastIndexOf("\\")+1); } var strSourceFolder = fso.BuildPath(strCurrentDir, "XPCOMWizard"); if (debug) { WScript.Echo("Source: " + strSourceFolder); } if (!fso.FolderExists(strSourceFolder)) { WScript.Echo("ERROR: Cannot find Wizard folder (should be: " + strSourceFolder + ")"); return ; } // vcprojects目录 var strProductDir = null; try { var strVC10Key = "HKLM\\Software\\Microsoft\\VisualStudio\\10.0\\Setup\\VC\\ProductDir"; strProductDir = shell.RegRead(strVC10Key); } catch(e) { try { var strVC10Key_x64 ="HKLM\\Software\\Wow6432Node\\Microsoft\\VisualStudio\\10.0\\Setup\\VC\\ProductDir"; strProductDir = shell.RegRead(strVC10Key_x64); } catch(e) { WScript.Echo("ERROR: Cannot find where Visual Studio 10.0 is installed."); return; } } var strDestFolder = fso.BuildPath(strProductDir, "vcprojects"); if (debug) { WScript.Echo("Destination: " + strDestFolder); } if (!fso.FolderExists(strDestFolder)) { WScript.Echo("ERROR: Cannot find destination folder (should be: " + strDestFolder + ")"); return; } // 拷贝配置文件 try { fso.CopyFile(fso.BuildPath(strSourceFolder, "XPCOMWizard.ico"), fso.BuildPath(strDestFolder, "XPCOMWizard.ico")); fso.CopyFile(fso.BuildPath(strSourceFolder, "XPCOMWizard.vsz"), fso.BuildPath(strDestFolder, "XPCOMWizard.vsz")); } catch(e) { var strError = "no info"; if (e.description.length != 0) strError = e.description; WScript.Echo("ERROR: Cannot copy file (" + strError + ")"); return; } // Create XPCOM folder try { var strDestXPCOMFolder = fso.BuildPath(strDestFolder, "XPCOM"); if (!fso.FolderExists(strDestXPCOMFolder)) fso.CreateFolder(strDestXPCOMFolder); if (debug) { WScript.Echo("XPCOM Folder: " + strDestXPCOMFolder); } fso.CopyFile(fso.BuildPath(strSourceFolder, "XPCOMWizard.vsdir"), fso.BuildPath(strDestXPCOMFolder, "XPCOMWizard.vsdir")); } catch(e) { var strError = "no info"; if(e.description.length != 0) strError = e.description; WScript.Echo("ERROR: Cannot create XPCOM folder (" + strError + ")"); return; } // Copy File try { var strDestFolder = fso.BuildPath(strProductDir, "VCWizards"); if (!fso.FolderExists(strDestFolder)) fso.CreateFolder(strDestFolder); strDestFolder = fso.BuildPath(strDestFolder, "AppWiz"); if (!fso.FolderExists(strDestFolder)) fso.CreateFolder(strDestFolder); strDestFolder = fso.BuildPath(strDestFolder, "XPCOMWizard"); if (!fso.FolderExists(strDestFolder)) fso.CreateFolder(strDestFolder); if (debug) { WScript.Echo("XPCOMWizard Folder: " + strDestFolder); } fso.CopyFolder(strSourceFolder, strDestFolder); } catch(e) { var strError = "no info"; if (e.description.length != 0) strError = e.description; WScript.Echo("ERROR: Cannot copy XPCOMWizard folder (" + strError + ")"); return; } WScript.Echo("XPCOMWizard Wizard successfully installed!"); } |
这样就可以在VS中直接建立XPCOM的模板项目。
5.打开VS2010,在VS2010中,新建项目,如下图向导:
选好工程目录,然后点确定。
6.选择XULRUNNER的sdk包。如下图:
7.完成。然后自动生成的工程如下:
其中重点关注的是图中
标号1,是接口的声明和被外部调用的方法。变成后,单独编译此文件,可以自动生成相应的头文件和实现文件。
标号3,是外部调用的实现
标号2,是测试的js和js调用
标号4,是测试时要改的ID好,防止缓存,每次调JS测试时都要改ID号。否则测试不成功。
8.建立js回调的IDL,js回调,也就是XPCOM的计算结果写到JS中,让页面来调用,实现C++和JS的交互。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
//这里的UUID可以通过VS【工具->创建GUID】自动生成 [scriptable, uuid(B62F393E-5122-4C4F-B189-5C69065155C9)] interface IJSCallBack: nsISupports { //这里的第一参数是标识,不能去掉,不然js回调不成功,一般默认的第一个标识的值默认为0 //对于数据的结果,string类型其实不是XPCOM的类型,当遇到中文的时候往往会乱码,后面详细说 //怎样转GBK都UTF8在页面上显示 boolean call(in long bogus,in string aData); }; [scriptable, uuid(671285FA-0055-438D-9F06-3169D99CF859)] interface IXPCOMWizard55: nsISupports { void Hello(); //对于回调的JS直接用上面生成的接口作为输入类型就可以。 //对于输出的参数,可以用out,但是在js中传入,一定要传入一个数组,也就是类型地址,才能正确的返回 //当然要是觉得麻烦,也可以通过返回类型来做这个传出值。如下面: //long Sum(in long nFirst,in long nSecond,in IJSCallBack jsCallBack); void Sum(in long nFirst,in long nSecond,in IJSCallBack jsCallBack,out long nResult); }; |
完成IDL后,直接编译就可以。会自动生成相应的接口。
相应实现的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
/** * @brief Say hello */ NS_IMETHODIMP XPCOMWizard55::Hello() { #if defined(XP_WIN) ::MessageBoxW(NULL, L"Hello, XPCOM!", L"XPCOMWizard55", MB_OK|MB_ICONINFORMATION); #endif return NS_OK; //return NS_ERROR_NOT_IMPLEMENTED; } /* void Sum (in long nFirst, in long nSecond, out long nResult); */ NS_IMETHODIMP XPCOMWizard55::Sum(int32_t nFirst, int32_t nSecond, IJSCallBack *jsCallBack, int32_t *nResult) { //js输出值 *nResult = nFirst + nSecond; char szResult[256] = {0}; itoa(*nResult,szResult,10); if (jsCallBack) { bool bRet = false; //这里的第一个参数为0 jsCallBack->Call(0,szResult,&bRet); } return NS_OK; } |
这样就实现了简单的js回调。
9.编写测试main.js(上图标号2),JS代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
var test = { call: function (index, data) { alert("call back result"); alert(data); } } function doXpCOM() { try { //建立XPCOM的实例"@gw.com.cn/xpcomwizard55;1"是唯一的类值和XPCOM中一致。 var aXPCOMWizard55 = Components.classes["@gw.com.cn/xpcomwizard55;1"] .createInstance(Components.interfaces.IXPCOMWizard55); aXPCOMWizard55.Hello(); //输出值必须为数据,不然输出不正确 var nResult = {}; //调用XPCOM的方法,test直接写上面定义好的脚本函数 aXPCOMWizard55.Sum(3, 5, test, nResult); alert("Return result:"); alert(nResult.value); } catch (e) { alert(e); } } |
10.设置调试的应用程序。如下图:
11.编译,成功OK。
12.直接运行。结果如下图
OK成功!!
学习日记,兼职软件设计,软件修改,毕业设计。
本文出自 学习日记,转载时请注明出处及相应链接。
本文永久链接: https://www.softwareace.cn/?p=817
一条评论
https://developer.mozilla.org/zh-CN/docs/Mozilla/Tech/XPCOM/Guide/Creating_components/Setting_up_the_Gecko_SDK