Some Supplement and description of component development technology under XPCOM-LINUX

Source: Internet
Author: User

Some Supplement and description of component development technology under XPCOM--LINUX

Original article from: World Business comments icxo. com (date)
--------------------------------------------------------------------------------
Boise bjgxjob@163.com
--------------------------------------------------------------------------------
As a component technology implemented by Microsoft, COM technology plays an important role in the Windows platform station and can be seen in module reuse and cross-language communication. But today I want to introduce the com implementation in Linux ---- XPCOM, which is the basic technology used in the Mozilla Browser project. We can use C ++ to create the XPCOM component, in the C ++ client program or Mozilla browser, components are called through JavaScript scripts to reuse software modules.

1. Configure the development environment of XPCOM.
First download the gecko-SDK package from Mozilla FTP. This is the development package of XPCOM. The source code of Mozilla also includes this SDK. Decompress the tgz package and you can see that more than 10 directories are generated:
/SDK/gecko-SDK/
/SDK/gecko-SDK/XPCOM/bin
/SDK/gecko-SDK/XPCOM/IDL
/SDK/gecko-SDK/XPCOM/include
/SDK/gecko-SDK/NSPR

Here are some of the basic parts.
/SDK/gecko-SDK/XPCOM/bin contains the following files:
Xpidl: This is the IDL compiler used to generate C ++ header files or component-type library files based on IDL.
Regxpcom: this is a component registration job. If we call components in the Mozilla browser, we will not actually use this tool.
Xpt-dump: The Type Library viewing program, used to view component information in the. xpt file.
Libxpcomglue. A: This is the basic library file of XPCOM. It will be connected to our component library when generating components.
/SDK/gecko-SDK/XPCOM/IDL, which contains the IDL data type definition file.
/SDK/gecko-SDK/XPCOM/include, which contains the basic C ++ header file required to create XPCOM.
/SDK/gecko-SDK also contains other directories, such as/SDK/gecko-SDK/string/include, contains the C ++ header of the string class in XPCOM
Files. If you need to use these classes in our components, you only need to include necessary header files and library files.

2. Write the IDL file.
Here we first use a uuidgen (a command line program similar to Ms guidgen in Linux) to generate the uuid of the component. We will redirect the output to a text file and use it later, here is a simple example to demonstrate the component generation process.
The IDL file is as follows:
// Filename: nsimycom. IDL
// Begin IDL --------------------------------------
# Include nsisupports. IDL
[Scriptable, UUID (5217115e-11fe-4d01-966d-9b27ffda6498)]
Interface nsimycom: nsisupports // note that nsimycom is prefixed with "NSI,
// You can easily generate the corresponding class name in the subsequent C ++ file. The class name is the part after NSI, such as mycom;
// If the first three letters of the interface name are other characters, the Class Name of the C ++ class is usually _ myclass _
{
Void Hello (in string in_str, [retval] out string out_str );
};
// End IDL -----------------------------------------
Well, this component is very simple. There is only one interface and only one method. This method has a string input parameter in_str and a string return value out_str.

3. Compile the 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 no error occurs, an nsimycom. h file is generated in the current directory. This file is the c ++ header file generated by the IDL compiler corresponding to the above IDL file.

The nsimycom. h file generated by the compiler is as follows:
//--------------------------------------------------------
# Ifndef _ gen_nsimycom_h __
# DEFINE _ gen_nsimycom_h __
# Ifndef _ 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
/* 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 that forward the behavior of this interface to another object .*/

# Define ns_forward_nsimycom (_ )/
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 (_ )/
Ns_imethod Hello (const char * in_str, char ** out_str) {return! _? Ns_error_null_pointer: _ to-> hello
(In_str, out_str );}
# If 0

/* Use the code below as a template for the Implementation class for this interface .*/

/* Header file */

Class nsmycom: Public nsimycom
{
Public:
Ns_decl_isupports
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 implementation class template .*/
# Endif

# Endif/* _ gen_nsimycom_h __*/

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

 

As you can see from the above, xpidl generates the header file for the interface, and also includes the C ++ class template for the header file. The next step is as easy as possible,

We copy the code between # If 0 and # endif to the newly created nsmycom. h and nsmycom. cpp files respectively,

Note that there is new code. The following two files are generated.

// 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/mycom1_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 <cstdio>

# Include <cstdlib>

# Include <string>

Ns_impl_isupports1_ci (nsmycom, nsimycom) // The macro here has been modified: note the difference between this macro and 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: String 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 is the same as the above two classes. however, we can only generate a dynamic library of the above class as a component, and we still need to do one thing. implement component registration and creation functions. this is almost a fixed pattern.

The code below is similar to the implementation in MS and uses 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 nsmodulecomponentinfo components [] = {

{"Nsmycom component", ns_mycom_cid, ns_mycom_contractid, nsmycomconstructor, // here, "constructor" is fixed, and nsmycom is the 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 is the module name compiled by the module source code file: nsmycommodule

5. Make makefile, generate, and install components.
Now, we can compile the MAKEFILE file to compile the component we just compiled.

# Filename: makefile

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

CPP = g ++
Cppflags + =-fno-rtti-fno-exceptions-shared
Gecko_sdk_path =/SDK/gecko-SDK
Xpidl = $ (gecko_sdk_path)/XPCOM/bin/xpidl
# Generate the C ++ header file
Cppheader =-M Header
# Generate type library files
Typelib =-M typelib
Regdir =/usr/local/lib/mozilla-1.6
Outdir = $ (regdir)/components
Gecko_config_include =-include mozilla-config.h
Gecko_defines =-dxpcom_glue
Gecko_shortdes =-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/IDL

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) $ (gecko_idl) $ (cppheader) nsimycom. IDL
$ (Xpidl) $ (gecko_idl) $ (typelib) nsimycom. IDL

Nsmycom. O: nsmycom. cpp
$ (CPP) $ (gecko_config_include) $ (gecko_defines)
$ (Gecko_shortdes)-C nsmycom. cpp-O nsmycom. o

Nsmycommodule. O: nsmycommodule. cpp
$ (CPP) $ (gecko_config_include) $ (gecko_defines)
$ (Gecko_shortdes)-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, after make, G ++ will generate the libxpmycom. So library file in the current directory. nsimycom. xpt is the corresponding type file. Then install the component to the Mozilla component directory:
Make install

This component library and its corresponding Type Library nsimycom. xpt will be copied to/usr/local/lib/mozilla-1.6/components (to confirm your component directory, such as the mozilla1.4 directory is generally usr/local/lib/mozilla-1.4/components) directory.

In this case, we can start the Mozilla Browser from the console. In a series of information output by the browser, the component will be registered successfully.

6. Test the component in HTML/JavaScript.

The HTML is as follows:

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

<HTML>
<Head>
<Title>
Test the XPCOM component
</Title>
</Head>
<Body>

<SCRIPT>
Netscape. Security. privilegemanager. enableprivilege ("universalxpconnect ");
VaR mycom = components. classes [@ westsoft.org/mycomdesk1).createinstance ();
Mycom = mycom. QueryInterface (components. Interfaces. nsimycom );

Function testxpcom (f)

{
Netscape. Security. privilegemanager. enableprivilege (universalxpconnect );
VaR ret_string;
Ret_string = mycom. Hello (document. form_test.input_string.value );
Alert (ret_string );
}
</SCRIPT>

<Form name = form_test>
Input information:
<Textarea name = input_string Cols = 70 rows = 5> </textarea>
<Input type = button value = testxpcom onclick = testxpcom (this. form);>
</Form>
</Body>
</Html>
//--------------------------------------------------

Open the HTML in Mozilla and enter some text in the input box. After you click testxpcom, how can we see the information returned from the component?
In addition, if the input information above is Chinese, garbled characters will be generated in the returned results. In IDL com IDL, there are native string, wstring, and other string types that support Unicode, these types can be used to solve the problem of Chinese character encoding. The following is my method.
Assume that XPCOM has normally obtained the gb2312 Chinese character encoding data. to properly interpret and display the encoding data on the test page by JavaScript, you must convert gb2312 to unicode encoding. Before that, you need to modify the previously defined IDL file nsimycom. IDL. For example, modify 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 wstring out_str );
};
// End IDL -----------------------------------------
After the corresponding header file is generated, modify the C ++ class file and compile it. After installation, the system can display Chinese Characters in Mozilla.
The code for converting gb2312 to Unicode is as follows:
// Begin -------------------------
# Include <iconv. h>
# Define max_path 400
Char * 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 (ucoutunicode, TMP, (norglen-noutlenleft ));
Iconv_close (CD );
Return strret;
}

// End --------------------------

The above is only a demonstration of the basic technology of the XPCOM component, and many other content is not mentioned. If you want to apply this technology to the project, please refer to Mozilla's online resources for more information.

The above is according to the "component development technology under the XPCOM--LINUX" to make a supplement, hope to help developers in this regard, do not have to please give advice!
If you have any questions contact me: bjgxjob@163.com

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.