Building a C++ XPCOM Component in Windows

I’ve been teaching myself to write Firefox extensions for the last few weeks, and became interested in XPCOM components. Unfortunately, I couldn’t find a good (and recent) summary of them, and had to spend 3 or 4 days cobbling together various tutorials, so I figured it’s time to write one.

What is XPCOM?

XPCOM is a language-agnostic communication platform used in Mozilla products (and some other random pieces of software) to allow code (specifically extensions) to be written in a wide variety of languages.

Why would I want to use XPCOM?

There are two ways to “use” XPCOM. First, you can call functions through XPCOM. For example, the Firefox bookmarks service uses an XPCOM interface. So in order to interact with this service from Javascript you would do something like:

var bmarks = Components.classes["@mozilla.org/browser/bookmarks-service;1"].getService();
bmarks.QueryInterface(Components.interfaces.nsIBookmarksService);
bmarks.addBookmarkImmediately("http://www.mozilla.org","Mozilla",0,null);

There are plenty of tutorials on doing this as it is the more common use for XPCOM, so I won’t go into any detail on it here.

The second way is to write an XPCOM service. That is what this tutorial covers. Sometimes you need extra functionality, speed, or just want to tie into some library that requires a different language. Most commonly this is C++, but there is also JavaXPCOM and PyXPCOM (and probably a few others). I’ll be talking about C++, since it’s what I needed for my project.

Warnings

  1. Before you trudge through this: you most likely are in the wrong place. Firefox extensions are usually all Javascript. If you can use JS to do what you want, stop now. There is no need to go through the complexity of an XPCOM component when you can just use JS. Go read a tutorial about writing extensions and get to work.
  2. There is something called ctypes coming to FF 3.7 that may make doing this a lot easier. I haven’t touched this at all, but it may be worth considering if you can wait for the functionality and only need to tie into a particular DLL for some functionality. Long story short, XPCOM may become the more difficult way to call C++ functions from FF extensions.

My Setup

  • Windows 7
  • Visual C++ Express 2008 (free from Microsoft’s website)
  • Firefox 3.6 (Gecko 1.9.2)
  • A UUID or GUID generator. This is a unique (read: random) ID that identifies your app to the world. Windows and Linux have tools to generate this (guidgen & uuidgen, respectively), or you can find various online generators (Mozilla links to several). I recommend this one since it gives you the C++ encoded form too, which you will need. You need two different UUIDs: one for your interface and one for your component.
  • Ability to read and understand C++

Sample Code

If you don’t want to go through the tutorial and just want everything to work, then download this sample code. Just follow step #1 of the tutorial, then make sure your Gecko SDK directory is set right in the build step, and you can breeze on by most of this article.

The Tutorial

This is mostly paraphrased from Alex Sirota’s great tutorial, but it hasn’t been updated since 2005 and is a bit outdated. This new one should work out of the box for FF 3.6.

This tutorial will create a component called MyComponent with one function: Add, which will take 2 numbers and, surprisingly, return the sum.

  1. Download the Gecko SDK for your version of Firefox. I used 1.9.2 for FF 3.6.
  2. Create an idl file – IMyComponent.idl, with the following (replacing ***IUID*** with your interface UUID):
    #include "nsISupports.idl"
    
    [scriptable, uuid(***IUID***)]
    interface IMyComponent : nsISupports
    {
      long Add(in long a, in long b);
    };

    This file is a language-agnostic interface definition which you can read more about here.

  3. Generate the interface header and typelib files out of the interface definition file. Assuming you extracted the Gecko SDK to C:\xulrunner-sdk\, run the following commands (from the directory you saved IMyComponent.idl to):
    C:\xulrunner-sdk\sdk\bin\xpidl.exe -m header -I C:\xulrunner-sdk\idl .\IMyComponent.idl
    C:\xulrunner-sdk\sdk\bin\xpidl.exe -m typelib -I C:\xulrunner-sdk\idl .\IMyComponent.idl

    These will create IMyComponent.h and IMyComponent.xpt, respectively.

  4. IMyComponent.h has two snippits of code that you can use for the next two files. Everything between /* Header file */ and /* Implementation file */ can be used for MyComponent.h:
    1. Start by inserting double inclusion protection code and the right include:
      #ifndef _MY_COMPONENT_H_
      #define _MY_COMPONENT_H_
      
      #include "IMyComponent.h"
    2. Add the following lines, which define your component name, contract ID, and CUID (where ***CUID*** is the C++-style component UUID, of the form { 0×12345678, 0x9abc, 0xdef0, { 0×12, 0×34, 0×56, 0×78, 0x9a, 0xbc, 0xde, 0xf0 } }):
      #define MY_COMPONENT_CONTRACTID "@example.com/XPCOMSample/MyComponent;1"
      #define MY_COMPONENT_CLASSNAME "A Simple XPCOM Sample"
      #define MY_COMPONENT_CID ***CUID***
    3. Copy in the snippet from IMyComponent.h, replacing all the instances of _MYCLASS_ with the name of your component (MyComponent).
    4. Finish off the double inclusion protection code with #endif //_MY_COMPONENT_H_
  5. Everything between /* Implementation file */ and /* End of implementation class template. */ can be used for MyComponent.cpp:
    1. Start by inserting the right include:
      #include "MyComponent.h"
    2. Copy in the snippet from IMyComponent.h, replacing all the instances of _MYCLASS_ with the name of your component (MyComponent).
    3. Add some implementation to the Add method. I replaced return NS_ERROR_NOT_IMPLEMENTED; with
      	*_retval = a + b;
      return NS_OK;
  6. Create your module definitions files:
    #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)

You now have all of the files needed to build an XPCOM component:

IMyComponent.h
IMyComponent.idl
IMyComponent.xpt
MyComponent.cpp
MyComponent.h
MyComponentModule.cpp

Now comes the hard part: getting the damn thing to build.

Building the code

Ok, it’s actually not hard since I’ve done most of the legwork for you. Assuming you’re using Visual C++ 2008 here are the settings you need (again assuming C:\xulrunner-sdk is where your Gecko SDK is). In Project->Properties:

Configuration Properties
  General
    Configuration Type: .dll
  C/C++
    General
      Additional Include Directories: C:\xulrunner-sdk\include
    Preprocessor
      Preprocessor Definitions: XP_WIN;XP_WIN32;XPCOM_GLUE_USE_NSPR
  Linker
    General
      Additional Library Directories: C:\xulrunner-sdk\lib
    Input
      Additional Dependencies: nspr4.lib xpcom.lib xpcomglue_s.lib

If you put the idl file into your project, be sure to mark it “Excluded from Build” in its properties…we don’t want VS touching it.

Cross your fingers, pray to whatever deity you believe in, and hit the build button. If it didn’t work let me know why in the comments and I’ll try to build a troubleshooting section.

Installing/Testing the Code

  1. Copy two files to C:\Program Files\Mozilla Firefox\components:
    • The DLL the build generated
    • IMyComponent.xpt
  2. Normally, if this was installed as part of an extension, it would automatically search this directory and find these files. But now we have to force a refresh. Delete xpti.dat. and compreg.dat from your profile directory (FF will regenerate them on next restart)
  3. Close Firefox and open it with this test file (MyComponentTest.html in the sample code):
    <html>
    <script type="text/javascript">
    function MyComponentTestGo() {
    	try {
    		// normally Firefox extensions implicitly have XPCOM privileges, but since this is a file we have to request it.
    		netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
    		const cid = "@example.com/XPCOMSample/MyComponent;1";
    		obj = Components.classes[cid].createInstance();
    		// bind the instance we just created to our interface
    		obj = obj.QueryInterface(Components.interfaces.IMyComponent);
    	} catch (err) {
    		alert(err);
    		return;
    	}
    	var res = obj.Add(3, 4);
    	alert('Performing 3+4. Returned ' + res + '.');
    }
    </script>
    <body>
    <button onclick="MyComponentTestGo();">Go</button>
    </body>
    </html>
  4. One last time: cross your fingers, pray to whatever deity you believe in, and hit the Go button. If it didn’t work let me know why in the comments and I’ll try to build a troubleshooting section.

Hopefully this clears up what looked like a lot of confusion to me. I will keep this updated to the best of my abilities and hopefully it will continue to be useful for a long time.

58 Responses to “Building a C++ XPCOM Component in Windows”

  1. jgershen says:

    Some more warnings might be appropriate –

    #3 – If you just got here from a search engine and this is your first time on the site, take note. Brian is extremely good at what he does, and while he doesn’t really make this sound easy, it’s still harder than it looks. The guy worked for Mozilla (admittedly not on this) and does webdev professionally. My point is, just keep in mind that getting XPCOM to work is absolutely nontrivial.

    #4 – If you’re trying to get XPCOM to work on OS X… well, honestly, you should really try to think about another way of accomplishing your goal. Before I committed to compiling an XPCOM component on a Mac, I would wait and see if ctypes magically solved all of my problems.

    TL;DR – its harder than it looks.

  2. Your blogging software doesn’t know the difference between 0x12 (U+0078 Latin Small Letter X) and 0×12 (U+00D7 Multiplication Sign).

  3. Appa says:

    Any hope you could describe the compiling of this on linux? Thanks.

  4. Brian says:

    @Appa: Not incredibly high on my TODO list, but I may eventually toy with it if I go back to a Linux desktop.

  5. Jesse Jackman says:

    Thanks for the post it was a huge help

  6. gil says:

    Hello,
    Thanks, I compiled it on linux with the makefile at the end of this page:
    http://groups.google.fr/group/mozilla.dev.tech.xpcom/tree/browse_frm/month/2008-12/58e0638e17596c16?rnum=1&_done=%2Fgroup%2Fmozilla.dev.tech.xpcom%2Fbrowse_frm%2Fmonth%2F2008-12%3F
    I ontained a “.so”
    I did all the end of the procedure but when I went on the htmlpage and I click on the button I get :
    “TypeError: Components.classes[cid] is undefined”
    so bad for me…
    I have firefox 3.5.8, i have compiled with sdk 1.9.1.7 and 1.9.2, same result…

  7. Brian says:

    @gil: Did you copy the .xpt file and the .so file into the right folder? That error means that it’s not actually loading your component, so either you’re referencing the component wrong (wrong name), it didn’t build correctly, or you didn’t put it in the right place.

    Let me know if that helps.

  8. gil says:

    Yes I put them in good directory, (delete xpti.dat and compreg.dat)
    when restart Firefox, in tools–>error concsole, I’ve got this 3 errors :
    “Failed to load XPCOM component: /usr/lib/firefox-3.5.8/components/MyComponent.so”
    “Failed to load XPCOM component: /usr/lib/xulrunner-1.9.1.8/components/pyabout.py”
    “Failed to load XPCOM component: /usr/lib/xulrunner-1.9.1.8/components/py_test_component.py”

    I’ve tried too an install with the xpi method and it looks similar errors in the console…
    I make an install.rdf and a folder “components” that include the “.so” and the “.xpt”,then I pack them all in a “xpi”, is it equivalent to the first method?

  9. gil says:

    I’ve tested your tuto on windows and it works very well, thanks !
    even with the xpi method
    the problem is only on linux, so pgerhaps because I am on FF 3.5.8 on linux or my compilation script isn’t good…

    I’ll continue to devellop on windows waiting to find a solution on linux
    here’s the result of the command :
    ./run-mozilla.sh `which ldd` -r /usr/lib/firefox-3.5.8/components/MyComponent.so
    undefined symbol: _Z16NS_TableDrivenQIPvPK12QITableEntryRK4nsIDPS_ (/usr/lib/firefox-3.5.8/components/MyComponent.so)
    undefined symbol: _Z20NS_NewGenericModule2PK12nsModuleInfoPP9nsIModule (/usr/lib/firefox-3.5.8/components/MyComponent.so)
    linux-gate.so.1 => (0x00d85000)
    libnspr4.so => /usr/lib/libnspr4.so (0x00f94000)
    libplds4.so => /usr/lib/libplds4.so (0x00e17000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0×00110000)
    libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0×00546000)
    libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00a8c000)
    libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0×00612000)
    libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0x0099a000)
    libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0x00ec5000)
    /lib/ld-linux.so.2 (0×00225000)

  10. DavidNguyen says:

    Well,man. I did exactly what you guided above. Firstly, the errors come with some kind of missing nsISupports.idl and nsrootidl.idl. Then I copied those two into the same directory with my project. Another error came up saying that: “error MIDL2025 : syntax error : expecting an interface name or DispatchInterfaceName or CoclassName or ModuleName or LibraryName or a type specification near “%” “.

    What is going on here?
    Thank in advance.

  11. Andy says:

    Is there any other way, aside from putting most of my code in a DLL using this method, of writing a FF xtn that cannot be read openly by anyone?

    I want to write a commercial extension (ie it will be sold), but doing it in Javascript means anyone who buys it can copy the code, change it up a bit, and sell it as a competitor.

    I understand FF isn’t really set up as a platform for selling extensions (a whole debate in itself), but is there some way round this?

  12. Miro says:

    Hello,
    Does anyone solve the problem with undefined cid?
    I’ve notice that in file MyComponent.h is cid defined as “@mydomain.com/XPCOMSample/MyComponent;1″, but script in test page is calling other cid “@example.com/XPCOMSample/MyComponent;1″
    But even changing cid to righ value, doesn’t solve the problem.

    Well, I’ll take a closer look at these CID’s and send repot if succeed.

  13. gilles says:

    @Miro
    But be carfeul to regenerate an new “.h” and “.xpt” with xpidl after having modified the first “.h” source

  14. Rabbit says:

    Hi, I’ve tried many times to launch my component, but it’s still failed. I’ve theses errors in my error console :
    Failed to load XPCOM component: C:\Users\Sahbi\AppData\Roaming\Mozilla\Firefox\Profiles\mk4oj57p.default\extensions\{DDC359D1-844A-42a7-9AA1-88A850A938A8}\components\contenthandling.idl
    Failed to load XPCOM component: C:\Users\Sahbi\AppData\Roaming\Mozilla\Firefox\Profiles\mk4oj57p.default\extensions\{DDC359D1-844A-42a7-9AA1-88A850A938A8}\components\debugService.idl
    Failed to load XPCOM component: C:\Users\Sahbi\AppData\Roaming\Mozilla\Firefox\Profiles\mk4oj57p.default\extensions\{DDC359D1-844A-42a7-9AA1-88A850A938A8}\components\filterManager.idl

    I’ve placed the two files (.dll and .xpt) in the right folder so i do not understand

  15. Andrew says:

    Hi,

    I downloaded the example and built it using VS2008 on Vista. I am running firefox 3.6.3 and xul-runner sdk 1.9.2. I deployed the DLL and XPT file to the firefox components directory and deleted the xpti.dat and compreg.dat files. I got the dreaded “TypeError: Components.classes[cid] is undefined” error.
    I tried using dependency walker and it doesn’t look like firefox is even attempting to load the dll (can’t find any mention in the logs). I think that I must have something fundamental wrong… but don’t know what it is. Are there any articles on the loading process and any tools that help to debug it?

  16. Miro says:

    Hi,
    Well after some research and testing I found out these things:
    - make project exactly as in tutorial
    - use only one CID for all occurence in files (in MyComponent.h is wrong
    CID). Here is nice generator for CID
    http://mozilla.pettay.fi/cgi-bin/mozuuid.pl
    - when deleting files compreg.dat and xpti.dat I modify components.list
    (same location where you put DLL and XPT files) and add at the end of
    file “MyComponent.dll”.

    After all it worked

  17. Miro says:

    Other, probably better way, to solve problem with undefined cid is to register new component with regxpcom.exe.

    From Mozilla Developer Center:
    “The regxpcom Program

    An explicit way to register a component is to run the application regxpcom. Without any arguments passed to regxpcom, the program registers the component in the default component registry. We suggest that when you are testing your component in the Mozilla or Netscape client, you copy your component into the components directory in the client’s installation folder. When it is copied there, run regxpcom from the command line to register that component and all the others in that directory. ”

    regxpcom should be located in same dir as mozcrt19.dll
    for me it’s C:\Program Files\Mozilla Firefox\

    Hope this will help

  18. Rabbit says:

    Hi, i’ve also the “TypeError: Components.classes[cid] is undefined” error… I’ve tried the two ways you talked about Miro, but it didn’t work. Even with regxpcom.exe.

    I’ve tried to verify the CID, I generated again the files with xpidl.exe and build the .dll but it still did not work. I’ve always the same error. Even if I used the sample code given above, this doesn’t work.
    Could it be a problem if my FF version is 3.6.3 and xul-runner 9.1.2 ?

    Please, if someone could help

  19. Andrew says:

    Hi Miro,

    Thanks for the advice. I tried these but no luck. I think that I will just have to increase my knowledge of how firefox is working so that I can fault find the problem.

  20. Andrew says:

    Hi,

    I went through the example from scratch and it now works. Cool!

  21. Rabbit says:

    @Andrew
    Did you do something different ? Cause it still does not work for me!

  22. Miro says:

    Hello,
    I’ve tried make project again, but this time with some changed class names and slightly different interface definition. Visual C++ didn’t even compile. This is VC++ output:

    TestMachine.cpp
    Generating Code…
    Skipping… (no relevant changes detected)
    TestMachineModule.cpp
    Linking…
    Creating library C:\Users\miro\Desktop\XUL\project\TestMachine\Debug\TestMachine.lib and object C:\Users\miro\Desktop\XUL\project\TestMachine\Debug\TestMachine.exp
    TestMachine.obj : error LNK2019: unresolved external symbol __imp__NS_LogAddRef referenced in function “public: virtual unsigned long __stdcall TestMachine::AddRef(void)” (?AddRef@TestMachine@@UAGKXZ)
    TestMachine.obj : error LNK2019: unresolved external symbol __imp__PR_GetCurrentThread referenced in function “public: virtual unsigned long __stdcall TestMachine::AddRef(void)” (?AddRef@TestMachine@@UAGKXZ)
    TestMachine.obj : error LNK2019: unresolved external symbol __imp__NS_DebugBreak referenced in function “public: virtual unsigned long __stdcall TestMachine::AddRef(void)” (?AddRef@TestMachine@@UAGKXZ)
    TestMachine.obj : error LNK2019: unresolved external symbol __imp__NS_LogRelease referenced in function “public: virtual unsigned long __stdcall TestMachine::Release(void)” (?Release@TestMachine@@UAGKXZ)
    TestMachine.obj : error LNK2019: unresolved external symbol “unsigned int __fastcall NS_TableDrivenQI(void *,struct QITableEntry const *,struct nsID const &,void * *)” (?NS_TableDrivenQI@@YIIPAXPBUQITableEntry@@ABUnsID@@PAPAX@Z) referenced in function “public: virtual unsigned int __stdcall TestMachine::QueryInterface(struct nsID const &,void * *)” (?QueryInterface@TestMachine@@UAGIABUnsID@@PAPAX@Z)
    TestMachineModule.obj : error LNK2019: unresolved external symbol “unsigned int __cdecl NS_NewGenericModule2(struct nsModuleInfo const *,class nsIModule * *)” (?NS_NewGenericModule2@@YAIPBUnsModuleInfo@@PAPAVnsIModule@@@Z) referenced in function _NSGetModule
    C:\Users\miro\Desktop\XUL\project\TestMachine\Debug\TestMachine.dll : fatal error LNK1120: 6 unresolved externals

    Well apparently is something wrong with definitions made by macros in code. Or maybe with linking, dependencies or alike things.

    But compiling downloaded .vcproj is fine.
    Anybody has similar problem, or has already solve?

    To Brian:
    How did you exactly make this VC project?

  23. Stefan says:

    Hi,

    I’m writing a xpcom extension and i used your tutorial to build the xpcom component. It works fine on my computer but when I try to install this extension somewhere else than my development environment it’s not working any more (“TypeError: Components.classes[cid] is undefined”).
    I also built an extension only for testing with your project file and it’s the same result.

    Any ideas?

    I’m using WinXP, Visual Express 2010, Firefox 3.6.3 and Gecko 1.9.2.

    see also: http://forums.mozillazine.org/viewtopic.php?f=19&t=1865365

    thanks!

    /Stefan

    (btw, really great tutorial. good structure and easy to understand)

  24. Konstantin says:

    Dude thanks a lot for this, you have made my day, This was really helpful! I can not express how many howers i lost on this because of the old components that do not compile with the new xul-runner!

    class NS_NO_VTABLE NS_SCRIPTABLE IMyComponent : public nsISupports {
    public:

    NS_DEFINE_STATIC_IID_ACCESSOR(IMYCOMPONENT_IID)
    /* long Add (in long a, in long b); */
    NS_IMETHOD Add(PRInt32 a, PRInt32 b, PRInt32 *_retval) = 0;
    };

    tanks and keep with the good work

  25. vetrivel r says:

    Hi, i’ve also the “TypeError: Components.classes[cid] is undefined” error… I’ve tried the two ways you talked about Miro, but it didn’t work. Even with regxpcom.exe.

    I’ve tried to verify the CID, I generated again the files with xpidl.exe and build the .dll but it still did not work. I’ve always the same error. Even if I used the sample code given above, this doesn’t work.
    Could it be a problem if my FF version is 3.6.3 and gecko-sdk1.7 ?

    Please, if someone could help

  26. vetrivel r says:

    Its very urgent….
    Can anyone please reply me ASAP

  27. Brian says:

    @vetrivel r: You absolutely need to use a matching XULRunner version for your FF install. https://developer.mozilla.org/en/gecko_sdk#Downloading

  28. Yourikahn says:

    Hi, I follow all recomendation but still have Linking error, can anyone hemp me?

    xpcomglue_s.lib(nsCOMPtr.obj) : warning LNK4099: PDB ‘generated.pdb’ was not found with ‘C:\Documents and Settings\***\Bureau\FirefoxPlugin\xulrunner-sdk\lib\xpcomglue_s.lib’ or at ‘c:\documents and settings\***\bureau\xpcom\release\generated.pdb’; linking object as if no debug info
    1>xpcomglue_s.lib(nsComponentManagerUtils.obj) : warning LNK4099: PDB ‘generated.pdb’ was not found with ‘C:\Documents and Settings\***\Bureau\FirefoxPlugin\xulrunner-sdk\lib\xpcomglue_s.lib’ or at ‘c:\documents and settings\***\bureau\xpcom\release\generated.pdb’; linking object as if no debug info
    1>xpcomglue_s.lib(nsISupportsImpl.obj) : warning LNK4099: PDB ‘generated.pdb’ was not found with ‘C:\Documents and Settings\***\Bureau\FirefoxPlugin\xulrunner-sdk\lib\xpcomglue_s.lib’ or at ‘c:\documents and settings\***\bureau\xpcom\release\generated.pdb’; linking object as if no debug info
    1>xpcomglue_s.lib(nsMemory.obj) : warning LNK4099: PDB ‘generated.pdb’ was not found with ‘C:\Documents and Settings\***\Bureau\FirefoxPlugin\xulrunner-sdk\lib\xpcomglue_s.lib’ or at ‘c:\documents and settings\***\bureau\xpcom\release\generated.pdb’; linking object as if no debug info
    1>xpcomglue_s.lib(nsGenericFactory.obj) : warning LNK4099: PDB ‘generated.pdb’ was not found with ‘C:\Documents and Settings\***\Bureau\FirefoxPlugin\xulrunner-sdk\lib\xpcomglue_s.lib’ or at ‘c:\documents and settings\***\bureau\xpcom\release\generated.pdb’; linking object as if no debug info

  29. Konstantin says:

    Is it possible to post the same tutorial for linux (Eclipse kdevelop or Monodevelop)? I have build this for windows but i have real trouble to get that working in linux!

  30. Mariusz says:

    Hi Brian Krausz!

    1) I have firefox 3.6.3

    2) Download the Gecko SDK:
    http://releases.mozilla.org/pub/mozilla.org/xulrunner/releases/1.9.2/sdk/xulrunner-1.9.2.en-US.win32.sdk.zip

    3) I download your code:
    http://nerdlife.net/wp-content/uploads/2010/02/mycomponent.zip

    4) And compile your code

    5) Close firefox, Delete xpti.dat. and compreg.dat

    6) But i have error “TypeError: Components.classes[cid] is undefined” too :)

    Very strange !!!!

    I publish my full code + SDK

    xulrunner-sdk_AND_MyComponent.zip
    http://www.mediafire.com/download.php?tdnmz0dijyt
    or
    http://rapidshare.com/files/400335658/xulrunner-sdk_AND_MyComponent.zip.html

    Brian !!!!!
    I have big request to You !!!!
    Can you download file and test XPCOM in your computer ?
    Install DLL+XPT and test in your firefox.
    Mayby is error in compile time ? And DLL is wrong ??

  31. chbambov says:

    Hello i found a way to register your component – in %ProgramFiles%\Mozilla Firefox\components there is a file named “componets.list”. Just simply add name of your dll file, this will force the registration (remember to delete compreg.dat from your profile directory before staring firefox.exe).

    NOTE: this is valid for Firefox 3.6.3 and gecko 1.9.3. Probably in next relases you will have to care about registration changes – https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_1.9.3

  32. mbrubin says:

    Miro’s suggestion of editing the components.list file is what did the trick for me. Running regxpcom as various tutorials suggest did not add my component to the components.list, but maybe I did something wrong there. In trying to figure out why I needed to use components.list, I found the following, very useful discussions:
    http://blog.vlad1.com/2009/10/23/firefox-application-directory-lockdown/
    https://developer.mozilla.org/en/Migrating_raw_components_to_add-ons
    Basically, as of Firefox 3.6, Mozilla is actively trying to keep developers from dumping their XPCOM components into the default components directory. I’m brand new to extension development, but my current take is that modifying components.list and using the default components directory is still a good way to get yourself going (there are enough moving parts as it is to get in order to get yourself up and running), but once up and running, you should migrate your raw component to an add-on, as the second article discusses.

  33. @Miro
    Thank you very much! I tried to compile some XPCOM component for some days. I’ve read many articles for novices with similar sample projects.

    By the way. There is another yet CID that should be changed. I mean

    const cid = “@mydomain.com/XPCOMSample/MyComponent;1″;

    in MyComponentTest.html. It should be the same as in MyComponent.h

    #define MY_COMPONENT_CONTRACTID “@mydomain.com/XPCOMSample/MyComponent;1″

  34. Mazhar says:

    @Miro
    I don’t need to update components.list. but it works. also i wrote an article in codeproject “http://www.codeproject.com/KB/miscctrl/XPCOM_Creation.aspx”

  35. Nitesh says:

    how to display the string value in xpcom component in mac .i have written the component that will work for both windows and linux..
    I have taken the example from
    https://developer.mozilla.org/en/how_to_build_a_binary_xpcom_component_using_visual_studio

    Can anyone please reply me ASAP.
    thanks in advance ..

  36. Hi, is there a way to implement in XPCOM events callback as well? Similar as we can do it with typical COM (activeX) intercating with js code?
    Thanks in advance
    Jarek

  37. NItesh says:

    Can anybody know how to display string in xpcom component for MAC PC 10.4 version.i have tried from so many tutorial and example but nothing going to be worked ..i need a help to resolve this issue..i have tried the same example
    https://developer.mozilla.org/en/how_to_build_a_binary_xpcom_component_using_visual_studio which has worked in both Linux and windows ..
    the addition of the 2 number i can able to display in MAC PC but cannot able to display string …

    can Anybody tell what was wrong so that it is not displaying string.i have downloaded the GEcko-Sdk 1.9.2 for MACi386 from https://developer.mozilla.org/en/gecko_sdk ..

    Can anyone please reply me ASAP.
    thanks in advance ..

  38. Andrey says:

    @chbambov

    I tried to use %ProgramFiles%\Mozilla Firefox\components there is a file named “componets.list” to register component. But it can not help. FiteFox 3.6.8 doesn’t see my component. Then I increased BuildID in ProgramFiles%\Mozilla Firefox\application.ini, and FF recognised component

  39. Martin says:

    Like many others I arrived here because of the following error:
    “TypeError: Components.classes[cid] is undefined”

    Brian’s tutorial is great but don’t use his sample code as a shortcut because there is a match error in the CONTRACT/CIDs. From his zipped and downloadable source:

    In MyComponent.h it’s defined as follows:
    #define MY_COMPONENT_CONTRACTID “@mydomain.com/XPCOMSample/MyComponent;1″

    In MyComponentTest.html it’s defined as:
    const cid = “@example.com/XPCOMSample/MyComponent;1″;

    Follow his tutorial though and it works great!

    Martin.

  40. Martin says:

    @Martin

    Fixed: “TypeError: Components.classes[cid] is undefined”

    I was a bit premature with the ‘success’ note above and wanted to share a bit more info:

    Even after following the tutorial to the letter, I got the same “TypeError: Components.classes[cid] is undefined”. However, after another day of trying, I solved the problem by reverting to xulrunner-1.8.0.4. The xpidl.exe which is part of that xulrunner is significantly smaller than the newer 1.9.2.

    So, my setup was as Brian’s, except for the gecko-sdk.

    I sure hope things get easier with FF4!

  41. IByte says:

    I wish to thank you for this tutorial, Brian, and in particular for the comment about using ctypes instead. I’ve been working on an update of my extension for Firefox 4 (beta 7) recently, and instead of reworking my XPCOM component to be compatible, I chose to use ctypes, which is finally mature enough to do elaborate Windows API calls. It really is easier than XPCOM in C++: far less boilerplate code, plus you get all the benefits of working with an interpreted language like JS (no recompiling etc.)

  42. Claudia says:

    Hi,
    I still have the error “TypeError: Components.classes[cid] is undefined”
    even though i fixed the CONTRACTID.
    What is the problem?

    Thanks.

  43. Jason Lu says:

    Hi, brian!
    I use your tutorial but I still have problems when I try to add C++ component to thunderbird 3.1.9. It also shows me the problem mainly discussed in the forum:TypeError: Components.classes[cid] is undefined. I used XPCOMViewer to check the class and interface I registered. However, I can only find the interface. I couldn’t find the class and I think it’s the main reason to cause the problem that cid undefined. Could you please help me to solve this problem? Is there any different between FF and thunderbird developing?

  44. Jason Lu says:

    Notice everyone!!!
    I just solve the problem. That is to put the dll and xpt file into the “components” direction on the profile of your FF or thunderbird. Cheers!

  45. Julien says:

    Thanks Brian! Great tutorial, clear and concise. I really appreciated it.

  46. Petko says:

    Has anybody successfully compiled this with Gecko 2.0, so it can work with Firefox 4?

  47. Athir Nuaimi says:

    I don’t believe this works with Gecko 2.0. When you build the project, you get a number of errors including
    MyComponent.cpp
    error C3646: ‘NS_ATTR_MALLOC’ : unknown override specifier
    MyComponentModule.cpp
    erro C1083: Cannot open include file: ‘nsIGenericFactory.h’

  48. Ajish says:

    TypeError: Components.classes[cid]…
    I followed the exact step…
    Couple of doubts…
    Will UUID and CUID be same with just difference in writing d last 2 parts as 0x…
    also y this error have put .so and .xpi in every folder…but to no avail

  49. Michael says:

    I met with the same error “Components.classes[cid] is undefined”,and it takes me a lot of time to solve.fially I changed the BuildID into current date and the whole thing works properly!
    I used xulrunner 1.9.* windows 7 Visual Studio 2008.
    Hope this will help you.

  50. goseas says:

    where to change the buildID? i change the comp-module.cpp as below,
    finally,there is a error show xpcomglue_s.lib(nsCOMPtr.obj) : warning LNK4099: PDB“generated.pdb”

    #include “mozilla/ModuleUtils.h”
    #include “nsIClassInfoImpl.h”
    #include “comp-impl.h”
    #include “comp.h”

    ////////////////////////////////////////////////////////////////////////
    // With the below sample, you can define an implementation glue
    // that talks with xpcom for creation of component nsSampleImpl
    // that implement the interface nsISample. This can be extended for
    // any number of components.
    ////////////////////////////////////////////////////////////////////////

    ////////////////////////////////////////////////////////////////////////
    // Define the contructor function for the object nsSampleImpl
    //
    // What this does is defines a function nsSampleImplConstructor which we
    // will specific in the nsModuleComponentInfo table. This function will
    // be used by the generic factory to create an instance of nsSampleImpl.
    //
    // NOTE: This creates an instance of nsSampleImpl by using the default
    // constructor nsSampleImpl::nsSampleImpl()
    //
    NS_GENERIC_FACTORY_CONSTRUCTOR(CSpecialThing)

    // The following line defines a kNS_SAMPLE_CID CID variable.
    NS_DEFINE_NAMED_CID(SPECIALTHING_CID);

    // Build a table of ClassIDs (CIDs) which are implemented by this module. CIDs
    // should be completely unique UUIDs.
    // each entry has the form { CID, service, factoryproc, constructorproc }
    // where factoryproc is usually NULL.
    static const mozilla::Module::CIDEntry kSampleCIDs[] = {
    { &kSPECIALTHING_CID, false, NULL, CSpecialThingConstructor },
    { NULL }
    };

    static const mozilla::Module::ContractIDEntry kSampleContracts[] = {
    { SPECIALTHING_CONTRACTID, &kSPECIALTHING_CID },
    { NULL }
    };

    // Category entries are category/key/value triples which can be used
    // to register contract ID as content handlers or to observe certain
    // notifications. Most modules do not need to register any category
    // entries: this is just a sample of how you’d do it.
    // @see nsICategoryManager for information on retrieving category data.
    static const mozilla::Module::CategoryEntry kSampleCategories[] = {
    { “my-category”, “my-key”, SPECIALTHING_CONTRACTID },
    { NULL }
    };

    static const mozilla::Module kSampleModule = {
    mozilla::Module::kVersion,
    kSampleCIDs,
    kSampleContracts,
    kSampleCategories
    };

    NSMODULE_DEFN(nsSampleModule) = &kSampleModule;

    NS_IMPL_MOZILLA192_NSGETMODULE(&kSampleModule)

Leave a Reply