XPCOM - Component Development Technology under Linux

zhaozj2021-02-16  46

Xpcom

Component development technology under Linux

As a component technology implemented by Microsoft, COM technology has an important role in the Windows platform station, which can be seen in module reuse, cross-language communications, etc. But today I want to introduce the COM implementation under Linux ---- XPCOM, this is the basic technology used in the Mozilla browser project, we can use C to make XPCOM components, passed in the C client or Mozilla browser The JavaScript script calls the component to implement the software module multiplexing.

1. Configure the development environment of XPCOM.

First go to Mozilla's FTP to download the Gecko-SDK package, which is the development kit of XPCOM, and the SDK is also included in the source code of Mozilla. Unzip the TGZ package, you can see how much more than a dozen directory:

/ SDK / GECKO-SDK /

/ SDK / GECKO-SDK / XPCOM / BIN

/ SDK / GECKO-SDK / XPCOM / IDL

/ SDK / GECKO-SDK / XPCOM / INCLUDE

/ SDK / GECKO-SDK / NSPR

......

Here, some of the basic parts thereof will be described.

/ SDK / GECKO-SDK / XPCOM / BIN mainly includes some files:

XPIDL: This is an IDL compiler to generate a C header file or component type library file according to IDL.

RegXPCOM: This is a component registration, if we call components in the Mozilla browser, it does not use the tool.

XPT-DUMP: Type Library View Programs, used to view component information in the .xpt file.

LIBXPCOMGLUE.A: This is the basic library file of XPCOM, which will be connected to our component library when generating components.

/ SDK / GECKO-SDK / XPCOM / IDL contains the IDL data type definition file.

/ SDK / Gecko-SDK / XPCOM / include, which contains the basic C header file required to make XPCOM.

/ SDK / GECKO-SDK also includes other one from the directory, such as / SDK / SDK / Gecko-SDK / String / Include, which contains XPCOM constant string C headers

File, if you need to use these classes in our components, you only need to include the necessary header files and library files.

2. Write the IDL file.

Here, you must first use a uuidgen (a command line program similar to MS Guidgen under Linux) to generate the UUID of the component, we will redirect it to a text first, then you can use it, here we will give a simple Examples to demonstrate the generation process of components.

The IDL file is as follows:

// filename: nsimycom.idl

// begin IDL --------------------------------------

#include "nsisupports.idl"

[Scriptable, UUID (5217115E-11FE-4D01-966D-9B27FFDA6498)]

Interface NSIMYCOM: NSISUPPORTS

{

Void Hello (in string in_str, [retval "out string out_str);

}

// end IDL ---------------------------------------

Ok, the component is very simple, only one interface, and there is only one method, which has a string input parameter in_str, and has a string return value OUT_STR.

3. Compile this IDL file and complete the C implementation corresponding to the component.

/ sdk / gecko-sdk / xpcom / bin / xpidl -i / sdk / gecko-sdk / xpcom / bin / idl -m header nsimycom.IDL If there is no error, then a nsimycom.h file will be generated in the current directory. This file is a C header file generated by the IDL compiler corresponding to the IDL file above.

Here is the content of the NSIMYCOM.H file generated by the compiler:

/ / -------------------------------------------------------------------------------------------- ------------

#ifndef __gen_nsimycom_h__

#define __ge_nsimycom_h__

#ifndef __gen_nsisupports_h__

#include "nsisupports.h"

#ENDIF

/ * For idl files this don't want to include root idl files. * /

#ifNDEF NS_NO_VTABLE

#define ns_no_vtable

#ENDIF

/ * Starting Interface: nsimycom * /

#define ns_imycom_iid_str "5217115e-22FE-4D01-966D-9B27FFDA6498"

#define ns_imycom_iid /

{0x5217115e, 0x22FE, 0x4D01, /

{0x96, 0x6d, 0x9b, 0x27, 0xff, 0xDa, 0x64, 0x98}}

Class ns_no_vtable nsimycom: public nsisupports {

PUBLIC:

NS_DEFINE_STATIC_IID_ACCESSOR (ns_imycom_iid)

/ * void Hello (in string in_str, [retval] out string out_str); * /

NS_IMETHOD HELLO (const char * in_str, char ** out_str) = 0;

}

/ * Use this macro when declaring classes That IMPLEMENT this interface. * /

#define ns_decl_nsimycom /

NS_IMETHOD HELLO (const char * in_str, char ** out_str);

/ * Use this macro to declare functions this forward the behavior of this interface to another object. * /

#define ns_forward_nsimycom (_to) /

NS_IMETHOD HELLO (const char * in_str, char ** out_str) {return_to hello (in_str, out_str);}

/ * Use this macro to declare functions That Forward the Behavior of this Interface to Another Object in A Safe

Way. * /

#define ns_forward_safe_nsimycom (_to) /

NS_IMETHOD Hello (const char * in_str, char ** out_str) {return! _To? Ns_error_null_pointer: _to-> hello

(in_Str, Out_STR);

#if 0

/ * Use the code below as a template for the importation class for this interface. * // * Header file * /

Class nsmycom: public nsimycom

{

PUBLIC:

NS_DECL_ISUPPPPPPports

NS_DECL_NSIMYCOM

NSMYCOM ();

Virtual ~ nsmycom ();

/ * Additional members * /

}

/ * Implementation file * /

Ns_impl_isupports1 (nsmycom, nsimycom)

NSMYCOM :: nsmycom ()

{

/ * MEMBER Initializers and constructor code * /

}

NSMYCOM :: ~ nsmycom ()

{

/ * Destructor Code * /

}

/ * void Hello (in string in_str, [retval] out string out_str); * /

NS_IMETHODIMP NSMYCOM :: Hello (const char * in_str, char ** OUT_STR)

{

RETURN NS_ERROR_NOT_IMPLEMENTED;

}

/ * End of importation class template. * /

#ENDIF

#ENDIF / * __GEN_NSIMYCOM_H__ * /

/ / -------------------------------------------------------------------------------------------- ---------

As can be seen from the above, XPIDL generates a header file that should interface, but also includes a C class template implemented on the header file. It is very easy as the next step.

We copied the code between #IF 0 to #ENDIF to the new NSMYCOM.H and NSMYCOM.CPP files, respectively.

Note that there is new code, the following is the generated two files.

// filename: nsmycom.h

#include "nsimycom.h"

#define ns_mycom_cid /

{0x5217115e, 0x22FE, 0x4D01, {0x96, 0x6d, 0x9b, 0x27, 0xff, 0xda, 0x64, 0x98}}

// Similar to CLSID in Windows

#define ns_mycom_contractid "@ westsoft.org / mycom; 1" // Similar to PROGID in WINDOW;

Class nsmycom: public nsimycom

{

PUBLIC:

NS_DECL_ISUPPPPPPports

NS_DECL_NSIMYCOM

NSMYCOM ();

Virtual ~ nsmycom ();

/ * Additional members * /

}

// filename: nsmycom.cpp

#include "nsmycom.h"

#include "nsmemory.h"

#include

#include

#include

NS_IMPL_ISUPPORTS1_CI (NSMYCOM, NSIMYCOM) // The macro here has been modified.

NSMYCOM :: nsmycom ()

{

}

NSMYCOM :: ~ nsmycom ()

{

}

/ * void Hello (in string in_str, [retval] out string out_str); * /

NS_IMETHODIMP NSMYCOM :: Hello (const char * in_str, char ** OUT_STR)

{

Printf ("/ n ------------- / n"); Printf ("% s / n", in_str);

Std :: str - str_tmp = "Your Input is:";

STR_TMP = IN_STR;

* OUT_STR = (CHAR *) Malloc (str_tmp.length () 1);

* OUT_STR = (char *) STR_TMP.C_STR ();

Return ns_ok;

}

4. Complete the factory method and registration module of the component.

The implementation of the component itself can be above two classes. But we only have the above class to generate a dynamic library. We need to do one thing. We also need to do something. Implement the registration of the component and create a related function. This is almost It is a fixed mode.

Below is the code of this section, similar to the implementation in MS, with many macros:

#include "nsiGenericfactory.h"

#include "nsmycom.h"

NS_GENERIC_FACTORY_CONSTRUCTOR (NSMYCOM)

Static ns_method nsmycomregistrationproc (nsiComponentManager * Acompmgr,

NSIFILE * APATH, Const Char * RegistryLocation, Const Char * ComponentType, Const NSModuleComponentInfo * Info)

{

Return ns_ok;

}

Static ns_method nsmycomunregistrationProc (nsiComponentManager * Acompmgr,

NSIFILE * APATH, Const Char * RegistryLocation, Const NSModuleComponentInfo * Info)

{

Return ns_ok;

}

NS_DECL_CLASSINFO (NSMYCOM)

Static const nsmodulects [] = {

{"nsmycom component", ns_mycom_cid, ns_mycom_contractid, nsmycomconstructor,

NSMYCOMREGISTRATIONPROC / * NULL IF you dont need * /,

NSMYCOMUNREGISTRATIONPROC / * NULL IF you dont need one * /,

Null / * no factory designructor * /,

NS_CI_Interface_getter_name (nsmycom),

Null / * no language helper * /,

& Ns_classinfo_name (nsmycom)

}

}

NS_IMPL_NSGETMODULE (NSMYCOMMODULE, COMPONENTS)

5, make Makefile, build, install components

Ok, we can write the Makefile file to compile the components we have just prepared.

#filename: makefile

#Begine -------------------------------------

CPP = G

CPPFLAGS = -fno-rtti -fno-exceptions -shared

Gecko_sdk_path = / sdk / gecko-sdk

XPIDL = $ (gecko_sdk_path) / XPCOM / BIN / XPIDL

Cppheader = -m header

TYPELIB = -M Typelib

Regdir = /usr/local/lib/mozilla-1.6outdir = $ (regdir) / Components

Gecko_config_include = -include mozilla-config.h

Gecko_defines = -dxpcom_glue

Gecko_includes = -i $ (gecko_sdk_path) /

-I $ (gecko_sdk_path) / xpcom / incrude /

-I $ (gecko_sdk_path) / NSPR / Include

Gecko_ldflags = -l $ (gecko_sdk_path) / XPCOM / BIN -LXPCOMGLUE /

-L $ (gecko_sdk_path) / NSPR / BIN -LNSPR4

Gecko_idl = -i $ (gecko_sdk_path) / xpcom / id1

Build: idl nsmycom.o nsmycommodule.o

$ (CPP) $ (cppflags) -o libxpmycom.so $ (gecko_defines) /

$ (Gecko_ldflags) nsmycom.o nsmycommodule.o

CHMOD X libxpmycom.so

IDL: NSIMYCOM.IDL

$ (XPIDL) $ (CPPHEADER) NSIMYCOM.IDL

$ (XPIDL) $ (gecko_idl) $ (typeelib) nsimycom.idl

nsmycom.o: nsmycom.cpp

$ (CPP) $ (gecko_config_include) $ (gecko_defines) /

$ (Gecko_includes) -c nsmycom.cpp -o nsmycom.o

nsmycommodule.o: nsmycommodule.cpp

$ (CPP) $ (gecko_config_include) $ (gecko_defines) /

$ (Gecko_includes) -c nsmycommodule.cpp -o nsmycommodule.o

INSTALL:

CP NSIMYCOM.XPT $ (OUTDIR) /

CP libxpmycom.so $ (outdir) /

Clean:

Rm * .o

Rm * .so

Rm *. * ~

Rm * ~

#end -------------

If everything is correct, we will generate the libxpmycom.so library file in the current directory after our make. Then install the component into the component directory of Mozilla:

Make Install

The component library and corresponding type library nsimycom.xpt will be copied to /usr/local/lib/mozilla-1.6/components (To confirm your component directory, such as Mozilla1.4 directory is usually USR / local / lib / mozilla -1.4 / Components directory.

At this time we can launch the Mozilla browser from the console, in a series of information of the browser output, will have information that the component is registered successfully.

6. Test the component in HTML / JavaScript.

The HTML is as follows:

// ------------------------------------

</p> <p>Test XPCOM components</p> <p></ title></p> <p></ hEAD></p> <p><body></p> <p><script></p> <p>Netscape.security.privilegeManager.enablePrivilege ("UniversalXPConnect");</p> <p>Var mycom = components.classes [@ westsoft.org/mycom; "; ";mycom = mycom.queryinterface (components.interfaces.nsimycom);</p> <p>Function testXPCOM (f)</p> <p>{</p> <p>Netscape.security.privilegeManager.enablePrivilege ("UniversalXPConnect");</p> <p>Var ret_string;</p> <p>RET_STRING = mycom.hello (Document.form_Test.Input_string.value);</p> <p>Alert (Ret_String);</p> <p>}</p> <p></ script></p> <p><form name = "form_test"></p> <p>Enter information:</p> <p><textarea name = "infut_string" cols = "70" rows = "5"> </ textarea></p> <p><Input Type = "Button" value = "TestXPCOM" onclick = "TestXPCOM (this.form);">>>>>>>>>>>>>>></p> <p></ form></p> <p></ body></p> <p></ html></p> <p>/ / -------------------------------------------------------------------------------------------- -</p> <p>We open this html in Mozilla, enter some text in the input box, after clicking TestXPCOM, how do you see the information returned from the component?</p> <p>In addition, if the input information above is Chinese, it will generate garbled, and NSAString, WString, etc. in the XPCOM ID1 support Unicode string type. Since some conversions are involved in the passage of the parameters, it is not mentioned.</p> <p>The above is just the basic technology of XPCOM components, and there are still many things that are not mentioned. If you want to apply this technology to the project, please refer to Mozilla's online resources.</p></div><div class="text-center mt-3 text-grey"> 转载请注明原文地址:https://www.9cbs.com/read-21505.html</div><div class="plugin d-flex justify-content-center mt-3"></div><hr><div class="row"><div class="col-lg-12 text-muted mt-2"><i class="icon-tags mr-2"></i><span class="badge border border-secondary mr-2"><h2 class="h6 mb-0 small"><a class="text-secondary" href="tag-2.html">9cbs</a></h2></span></div></div></div></div><div class="card card-postlist border-white shadow"><div class="card-body"><div class="card-title"><div class="d-flex justify-content-between"><div><b>New Post</b>(<span class="posts">0</span>) </div><div></div></div></div><ul class="postlist list-unstyled"> </ul></div></div><div class="d-none threadlist"><input type="checkbox" name="modtid" value="21505" checked /></div></div></div></div></div><footer class="text-muted small bg-dark py-4 mt-3" id="footer"><div class="container"><div class="row"><div class="col">CopyRight © 2020 All Rights Reserved </div><div class="col text-right">Processed: <b>0.035</b>, SQL: <b>9</b></div></div></div></footer><script src="./lang/en-us/lang.js?2.2.0"></script><script src="view/js/jquery.min.js?2.2.0"></script><script src="view/js/popper.min.js?2.2.0"></script><script src="view/js/bootstrap.min.js?2.2.0"></script><script src="view/js/xiuno.js?2.2.0"></script><script src="view/js/bootstrap-plugin.js?2.2.0"></script><script src="view/js/async.min.js?2.2.0"></script><script src="view/js/form.js?2.2.0"></script><script> var debug = DEBUG = 0; var url_rewrite_on = 1; var url_path = './'; var forumarr = {"1":"Tech"}; var fid = 1; var uid = 0; var gid = 0; xn.options.water_image_url = 'view/img/water-small.png'; </script><script src="view/js/wellcms.js?2.2.0"></script><a class="scroll-to-top rounded" href="javascript:void(0);"><i class="icon-angle-up"></i></a><a class="scroll-to-bottom rounded" href="javascript:void(0);" style="display: inline;"><i class="icon-angle-down"></i></a></body></html><script> var forum_url = 'list-1.html'; var safe_token = 'AoItCw6px1im_2B0IZ_2BK_2BIPZGKlUZbMXBigew_2Bq_2B1FWF7oDavGBbhSs70XLDfXDMwwar7H23ePlFdcEzKLnnk78Q_3D_3D'; var body = $('body'); body.on('submit', '#form', function() { var jthis = $(this); var jsubmit = jthis.find('#submit'); jthis.reset(); jsubmit.button('loading'); var postdata = jthis.serializeObject(); $.xpost(jthis.attr('action'), postdata, function(code, message) { if(code == 0) { location.reload(); } else { $.alert(message); jsubmit.button('reset'); } }); return false; }); function resize_image() { var jmessagelist = $('div.message'); var first_width = jmessagelist.width(); jmessagelist.each(function() { var jdiv = $(this); var maxwidth = jdiv.attr('isfirst') ? first_width : jdiv.width(); var jmessage_width = Math.min(jdiv.width(), maxwidth); jdiv.find('img, embed, iframe, video').each(function() { var jimg = $(this); var img_width = this.org_width; var img_height = this.org_height; if(!img_width) { var img_width = jimg.attr('width'); var img_height = jimg.attr('height'); this.org_width = img_width; this.org_height = img_height; } if(img_width > jmessage_width) { if(this.tagName == 'IMG') { jimg.width(jmessage_width); jimg.css('height', 'auto'); jimg.css('cursor', 'pointer'); jimg.on('click', function() { }); } else { jimg.width(jmessage_width); var height = (img_height / img_width) * jimg.width(); jimg.height(height); } } }); }); } function resize_table() { $('div.message').each(function() { var jdiv = $(this); jdiv.find('table').addClass('table').wrap('<div class="table-responsive"></div>'); }); } $(function() { resize_image(); resize_table(); $(window).on('resize', resize_image); }); var jmessage = $('#message'); jmessage.on('focus', function() {if(jmessage.t) { clearTimeout(jmessage.t); jmessage.t = null; } jmessage.css('height', '6rem'); }); jmessage.on('blur', function() {jmessage.t = setTimeout(function() { jmessage.css('height', '2.5rem');}, 1000); }); $('#nav li[data-active="fid-1"]').addClass('active'); </script>