xpcom:js 回调
https://blog.****.net/ec06cumt/article/details/17507763
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的代码如下:
- 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的交互。
- //这里的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后,直接编译就可以。会自动生成相应的接口。
相应实现的代码如下:
- /**
- * @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代码如下:
- 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://blog.****.net/ec06cumt/article/details/17507763
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的代码如下:
- 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的交互。
- //这里的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后,直接编译就可以。会自动生成相应的接口。
相应实现的代码如下:
- /**
- * @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代码如下:
- 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成功!!