Building a C++ XPCOM Component in Windows

发布时间:2011-3-30 10:37
分类名称:Plugins


原文链接:http://nerdlife.net/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 JavaXPCOMand 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

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 abouthere.

  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, 0×9abc, 0xdef0, { 0×12, 0×34, 0×56, 0×78, 0×9a, 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. Deletexpti.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 >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.

================================================================================

  1. jgershen
    February 7th, 2010 at 17:25 | #1
    Reply | Quote

    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. Neil Rashbrook
    February 8th, 2010 at 08:45 | #2
    Reply | Quote

    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
    February 9th, 2010 at 09:18 | #3
    Reply | Quote

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

  4. Brian
    February 10th, 2010 at 01:12 | #4
    Reply | Quote

    @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
    February 25th, 2010 at 03:38 | #5
    Reply | Quote

    Thanks for the post it was a huge help

  6. gil
    February 25th, 2010 at 21:12 | #6
    Reply | Quote

    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
    February 26th, 2010 at 22:56 | #7
    Reply | Quote

    @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
    February 27th, 2010 at 03:55 | #8
    Reply | Quote

    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
    February 27th, 2010 at 17:39 | #9
    Reply | Quote

    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 => (0×00d85000)
    libnspr4.so => /usr/lib/libnspr4.so (0×00f94000)
    libplds4.so => /usr/lib/libplds4.so (0×00e17000)
    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 (0×00a8c000)
    libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0×00612000)
    libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0×0099a000)
    libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0×00ec5000)
    /lib/ld-linux.so.2 (0×00225000)

  10. DavidNguyen
    March 23rd, 2010 at 00:51 | #10
    Reply | Quote

    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
    March 31st, 2010 at 14:23 | #11
    Reply | Quote

    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
    April 7th, 2010 at 17:47 | #12
    Reply | Quote

    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
    April 10th, 2010 at 09:59 | #13
    Reply | Quote

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

  14. Rabbit
    April 11th, 2010 at 11:14 | #14
    Reply | Quote

    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
    April 12th, 2010 at 03:00 | #15
    Reply | Quote

    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
    April 12th, 2010 at 04:58 | #16
    Reply | Quote

    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
    April 12th, 2010 at 07:25 | #17
    Reply | Quote

    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
    April 12th, 2010 at 16:40 | #18
    Reply | Quote

    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
    April 12th, 2010 at 20:11 | #19
    Reply | Quote

    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
    April 14th, 2010 at 01:18 | #20
    Reply | Quote

    Hi,

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

  21. Rabbit
    April 14th, 2010 at 03:00 | #21
    Reply | Quote

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

  22. Miro
    April 16th, 2010 at 09:08 | #22
    Reply | Quote

    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
    April 24th, 2010 at 06:47 | #23
    Reply | Quote

    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
    April 28th, 2010 at 17:34 | #24
    Reply | Quote

    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
    May 6th, 2010 at 07:17 | #25
    Reply | Quote

    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
    May 6th, 2010 at 07:19 | #26
    Reply | Quote

    Its very urgent….
    Can anyone please reply me ASAP

  27. Brian
    May 6th, 2010 at 14:43 | #27
    Reply | Quote

    @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
    May 7th, 2010 at 11:59 | #28
    Reply | Quote

    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
    May 11th, 2010 at 17:01 | #29
    Reply | Quote

    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
    June 18th, 2010 at 06:44 | #30
    Reply | Quote

    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
    June 27th, 2010 at 07:34 | #31
    Reply | Quote

    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
    July 14th, 2010 at 13:48 | #32
    Reply | Quote

    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. Anatoly Kirsanov
    July 29th, 2010 at 08:05 | #33
    Reply | Quote

    @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
    July 29th, 2010 at 10:13 | #34
    Reply | Quote

    @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
    August 13th, 2010 at 03:45 | #35
    Reply | Quote

    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. Jarek Karciarz
    August 14th, 2010 at 09:26 | #36
    Reply | Quote

    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
    August 16th, 2010 at 02:02 | #37
    Reply | Quote

    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_studiowhich 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 fromhttps://developer.mozilla.org/en/gecko_sdk ..

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

  38. Andrey
    August 19th, 2010 at 08:16 | #38
    Reply | Quote

    @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
    August 25th, 2010 at 06:49 | #39
    Reply | Quote

    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
    August 26th, 2010 at 03:27 | #40
    Reply | Quote

    @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
    December 15th, 2010 at 20:43 | #41
    Reply | Quote

    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
    March 23rd, 2011 at 13:40 | #42
    Reply | Quote

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

    Thanks.