Creating a simple C++ component
Mozilla October 4th, 2006
在重新翻阅 << Creating Applications with Mozilla >> 以及 Alex Sirota 和 Lonecat 的帖子后, 总算对 XPCOM 有点入门了… 记录个简单的 C++ component 的例子, 作为以后的参考.
需要的软件: gecko-sdk
1. 建立一个 idl 文件(接口定义)
?Download IMyComponent.idl
1 2 3 4 5 6 7 | #include "nsISupports.idl" [scriptable, uuid(a765a62c-eb6a-4e4f-a1a8-c66340d3e892)] interface IMyComponent : nsISupports { long Add(in long a, in long b); }; |
其中的 uuid 可由 uuidgen 生成.
2. 使用 xpidl 生成相应的头文件和类型库文件
1 2 | xpidl -m header -I_DIR_ IMyComponent.idl xpidl -m typelib -I_DIR_ IMyComponent.idl |
“_DIR_” 替换为gecko-sdk/idl的路径
3. 建立自己组件的头文件
?Download MyComponent.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #ifndef _MY_COMPONENT_H_ #define _MY_COMPONENT_H_ #include "IMyComponent.h" #define MY_COMPONENT_CONTRACTID "@mozilla.org/MyComponent;1" #define MY_COMPONENT_CLASSNAME "A Simple XPCOM Sample" #define MY_COMPONENT_CID { 0xa765a62c, 0xeb6a, 0x4e4f, { 0xa1, 0xa8, 0xc6, 0x63, 0x40, 0xd3, 0xe8, 0x92 } } /* Header file */ class MyComponent : public IMyComponent { public: NS_DECL_ISUPPORTS NS_DECL_IMYCOMPONENT MyComponent(); virtual ~MyComponent(); /* additional members */ }; #endif //_MY_COMPONENT_H_ |
其中 /* Header file */ 下那段类的定义是从 xpidl 生成的 IMyComponent.h 文件里 copy 过来的, 然后把其中的 “_MYCLASS_” 改成自己的组件名.
4. 创建组件的实现文件(也就是cpp啦~)
?Download MyComponent.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include "MyComponent.h" NS_IMPL_ISUPPORTS1(MyComponent, IMyComponent) MyComponent::MyComponent() { /* member initializers and constructor code */ } MyComponent::~MyComponent() { /* destructor code */ } /* long Add (in long a, in long b); */ NS_IMETHODIMP MyComponent::Add(PRInt32 a, PRInt32 b, PRInt32 *_retval) { *_retval = a + b; return NS_OK; } |
其中的内容同样是来自 xpidl 生成的 IMyComponent.h , 拷贝其中的 /* Implementation file */ 段, 同样将 “_MYCLASS_” 改成自己的组件名.
5. 创建自己的模块定义文件
?Download MyComponentModule.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include "nsIGenericFactory.h" #include "MyComponent.h" NS_GENERIC_FACTORY_CONSTRUCTOR(MyComponent) static nsModuleComponentInfo components[] = { { MY_COMPONENT_CLASSNAME, MY_COMPONENT_CID, MY_COMPONENT_CONTRACTID, MyComponentConstructor, } }; NS_IMPL_NSGETMODULE("MyComponentsModule", components) |
6. 最后则是需要建立一个 Makefile 文件
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 | CXX = c++ CPPFLAGS += -fno-rtti \ -fno-exceptions \ -shared # Change this to point at your Gecko SDK directory. GECKO_SDK_PATH = /home/duo/gecko-sdk # GCC only define which allows us to not have to #include mozilla-config # in every .cpp file. If your not using GCC remove this line and add # #include "mozilla-config.h" to each of your .cpp files. GECKO_CONFIG_INCLUDE = -include mozilla-config.h GECKO_DEFINES = -DXPCOM_GLUE GECKO_INCLUDES = -I $(GECKO_SDK_PATH)/include GECKO_LDFLAGS = -L $(GECKO_SDK_PATH)/lib -lxpcomglue \ -lnspr4 \ -lplds4 FILES = MyComponent.cpp MyComponentModule.cpp TARGET = MyComponent.so build: $(CXX) -Wall -Os -o $(TARGET) $(GECKO_CONFIG_INCLUDE) $(GECKO_DEFINES) $(GECKO_INCLUDES) $(GECKO_LDFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(FILES) chmod +x $(TARGET) strip $(TARGET) clean: rm $(TARGET) |
7. 执行下 make , 就能得到我们想要的 MyComponent.so 了.
8. JavaScript 调用
1 2 3 4 5 6 7 8 9 | try { var obj = Components.classes["@mozilla.org/MyComponent;1"].createInstance(); obj = obj.QueryInterface(Components.interfaces.IMyComponent); } catch (err) { alert(err); return; } var res = obj.Add(3, 4); alert('Performing 3+4. Returned ' + res + '.'); |
9. 如果需要在 XULRunner 下使用, 那么将 MyComponent.so 和 IMyComponent.xpt 拷贝到您的应用程序的
components 目录, 同时别忘了将配置文件 ~/.companyname/appname/ 删除.
Related posts: