Some additional and descriptions of components development technology under Linux

xiaoxiao2021-03-06  81

Some complementary and description of component development technology under Linux Some supplements and descriptions Original: "World Business Review" ICXO.com (Date: 2004-07-14 13:56) ------------- -------------------------------------------------- ----------------- Boise Bjgxjob@163.com --------------------------- -------------------------------------------------- --- COM Technology As a component technology implemented by Microsoft, there is an important role in the Windows platform station, which can be seen in module reuse, cross-language communication, 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 month: / 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 contains some files: XPIDL: This is the IDL compiler to generate C header files or component type library files according to IDL .regXPCOM: This is the component registration work, if we are Mozilla browser calls the component, which does not use this 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. The / SDK / Gecko-SDK also contains other one from the directory, such as / SDK / SDK / Gecko-SDK / String / Include, which contains the C header file of the XPCOM constant string class, if we need to use it in our components Class, just 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 ----------------------------------- - # includable nsisupports.idl [Scriptable, UUID (5217115e-11FE-4D01-966D-9B27FFDA6498)] Interface nsimycom: nsisupports / / Here you need to pay attention to: nsimycom is prefixed in "nsi", // can be convenient The corresponding class name is generated in the C file, and the class named NSI, such as mycom; // If the interface is three letters as other characters, the generally generated C class name is _myclass_ {void Hello (in string in_str, [retval string out_str);}; // end idl ------------------------------- ---------- Well, the component is 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.

Below is the NSIMYCOM.H file generated by the compiler: // ------------------------------------ -------------------- # iFNDef __Gen_nsimycom_h __ # define __gen_nsimycom_h __ # gndef __gen_nsisupports_h __ # include nsisupports.h # ENDIF

/ * For idl files That Dont Want to include root IDl files. * / # IFNDef ns_no_vtable # define ns_no_vtable # endif / * start 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 that 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_isupports ns_decl_nsimycom nsmycom (); virtual ~ nsmycom (); / * additional memory * /};

/ * 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 in_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 WINDOWS;

Class nsmycom: public nsimycom

{public: ns_decl_isupports 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: Note The difference between the automatically generated C code: ns_impl_isupports1

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 (% SN, IN_STR); std :: 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 the 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, // herein, "Constructor" is fixed, nsMyCom class name nsMyComRegistrationProc / * NULL if you dont need one * /, nsMyComUnregistrationProc / * NULL if you dont need one * / , NULL / * no factory destructor * /, NS_CI_INTERFACE_GETTER_NAME (nsMyCom), NULL / * no language helper * /, & NS_CLASSINFO_NAME (nsMyCom)}}; NS_IMPL_NSGETMODULE (nsMyComModule, components) // nsMyComModule after the module source code file is compiled module name: NSMYCOMMODULE

5, make Makefile, generated, install components well, we can write makefile files to compile the components we have just prepared.

#filename: makefile

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

CPP = G cppflags = -fno-rtti -fno-eXceptions -shared gecko_sdk_path = / sdk / gecko-sdkXPIDL = $ (gecko_sdk_path) / xpcom / bin / xpidl # Generate C header file cppheader = -m header # generation type library file TYPELIB = -m typelibREGDIR = /usr/local/lib/mozilla-1.6OUTDIR = $ (REGDIR) / componentsGECKO_CONFIG_INCLUDE = -include mozilla-config.hGECKO_DEFINES = -DXPCOM_GLUE GECKO_INCLUDES = -I $ (GECKO_SDK_PATH) -I $ (GECKO_SDK_PATH) / XPCOM / INCLUDE-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 $ (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_interfines) $ (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.oinstall: cp nsIMyCom.xpt $ (OUTDIR) / cp libxpmycom.so $ (OUTDIR ) /

Clean: rm * .o rm * .so rm *. * ~ rm * ~ # end -------------

If everything is correct, after our make, G will generate libxpmycom.so library files in the current directory, nsimycom.xpt is the corresponding type file. Then install the component to 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:

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

Test XPCOM Components </ Title> </ head> <body></p> <p><Script> netscape.security.PrivilegeManager.enablePrivilege ( "UniversalXPConnect"); var mycom = Components.classes [@ westsoft.org / mycom; 1] .createInstance (); mycom = mycom.QueryInterface (Components.interfaces.nsIMyCom);</p> <p>Function testXPCOM (f)</p> <p>{Netscape.security.PrivilegeManager.enablePrivilege (UniversalXPConnect); var ret_string; ret_string = mycom.Hello (document.form_test.input_string.value); alert (ret_string);} </ script></p> <p><form name = form_test> Enter information: <textarea name = input_string cols = 70 rows = 5> </ textarea> <input type = button value = testXPCOM onclick = TestXPCOM (this.form);> </ form> </ body > </ html> // ------------------------------------------- -------</p> <p>We open this HTML in Mozilla, enter some text in the input box, how do you click TestXPCOM, how do you see the information returned from the component? In addition, the input information above is Chinese, then return to the garble There are NSAString, WString, etc. in XPCOM IDL Support Unicode string type, which can be used to solve the problem of Chinese character encoding. The following is what I use. It is assumed that the XPCOM has a normally acquired data of the Chinese character encoding of GB2312. To explain the encoding and displaying these encodings by JavaScript on the test page, you must convert GB2312 to Unicode encoding. Before this, you need to modify the IDL file defined in front: nsimycom.IDL, for example, modify the following: // 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 wstring out_str);}; // end idl ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -------- After generating the corresponding Header file, modify the C class file and compile. After installing, you can display the Chinese characters normally in Mozilla. The code that GB2312 is converted to Unicode is as follows: // Begin ------------------------- # include <iconv.h> #define max_path 400char * getunicode char * ucInGB2312, char * ucOutUnicode) {if (ucInGB2312 == NULL || ucOutUnicode == NULL) {return "/ 0";} char * strIn = ucInGB2312; char * strRet = ucOutUnicode; char tmp [MAX_PATH * 10] = {0}; char * ptmp = tmp; size_t ninlen = Strlen (ucingb2312); size_t noutlenleft = ninlen * 3; size_t norglen = ninlen * 3; iconv_t cd = 0; if ((cd = iconv_open ("unicode", "GB2312 ")) == (iconv_t) -1) {return" / 0 ";} if (Iconv (CD, & Strin, & Ninlen, & PTMP, & NOUTLENLEFT) == (size_t) -1) {return" / 0 ";} Memcpy (Ucoutunicate, TMP, (Norglen - Noutlenleft); iconv_close (CD); return strret;} // end --------------------------</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-100833.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="100833" 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.067</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 = 'fJjQ8j6RZCB5jFGy0WvQHurTSoIMNJspP_2B0hlBNwWzlYEYn6zm5ulou6jXyuwmoIwop3GE_2FZSkRShkwy'; 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>