- Timestamp:
- Jan 28, 2014 4:52:15 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/manual/en_US/SDKRef.xml
r49525 r50262 1719 1719 1720 1720 <sect2 id="cbinding"> 1721 <title>C binding to XPCOM API</title> 1722 1723 <note> 1724 <para>This section currently applies to Linux, Mac OS X and Solaris 1725 hosts only.</para> 1726 </note> 1727 1728 <para>Starting with version 2.2, VirtualBox offers a C binding for the 1729 XPCOM API.</para> 1730 1731 <para>The C binding provides a layer enabling object creation, method 1732 invocation and attribute access from C.</para> 1721 <title>C binding to VirtualBox API</title> 1722 1723 <para>The VirtualBox API originally is designed as object oriented, 1724 using XPCOM or COM as the middleware, which translates natively to C++. 1725 This means that in order to use it from C there needs to be some 1726 helper code to bridge the language differences and reduce the 1727 differences between platforms.</para> 1728 1729 <sect3 id="capi_glue"> 1730 <title>Cross-platform C binding to VirtualBox API</title> 1731 1732 <para>Starting with version 4.3, VirtualBox offers a C binding 1733 which allows using the same C client sources for all platforms, 1734 covering Windows, Linux, Mac OS X and Solaris. It is the 1735 preferred way to write API clients, even though the old style 1736 is still available.</para> 1737 1738 </sect3> 1733 1739 1734 1740 <sect3 id="c-gettingstarted"> 1735 1741 <title>Getting started</title> 1736 1742 1737 <para>The following sections describe how to use the C binding in a 1738 C program.</para> 1739 1740 <para>As part of the SDK, a sample program is provided which 1741 demonstrates using the C binding to initialize XPCOM, get handles for 1743 <para>The following sections describe how to use the VirtualBox API 1744 in a C program. The necessary files are included in the SDK, in the 1745 directories <computeroutput>sdk/bindings/c/include</computeroutput> 1746 and <computeroutput>sdk/bindings/c/glue</computeroutput>.</para> 1747 1748 <para>As part of the SDK, a sample program 1749 <computeroutput>tstCAPIGlue.c</computeroutput> is provided in the 1750 directory <computeroutput>sdk/bindings/c/samples</computeroutput> 1751 which demonstrates 1752 using the C binding to initialize the API, get handles for 1742 1753 VirtualBox and Session objects, make calls to list and start virtual 1743 1754 machines, monitor events, and uninitialize resources when done. The 1744 program uses the VBoxGlue library to open the C binding layer during 1745 runtime.</para> 1746 1747 <para>The sample program 1748 <computeroutput>tstXPCOMCGlue</computeroutput> is located in the bin 1749 directory and can be run without arguments. It lists registered 1750 machines on the host along with some additional information and ask 1751 for a machine to start. The source for this program is available in 1752 <computeroutput>sdk/bindings/xpcom/cbinding/samples/</computeroutput> 1753 directory. The source for the VBoxGlue library is available in the 1754 <computeroutput>sdk/bindings/xpcom/cbinding/</computeroutput> 1755 directory.</para> 1755 sample program is trying to illustrate all relevant concepts, so it 1756 is a great source of detail information. Among many other generally 1757 useful code sequences it contains a function which shows how to 1758 retrieve error details in C code if they are available from the API 1759 call.</para> 1760 1761 <para>The sample program <computeroutput>tstCAPIGlue</computeroutput> 1762 can be built using the provided <computeroutput>Makefile</computeroutput> 1763 and can be run without arguments.</para> 1764 1765 <para>It uses the VBoxCAPIGlue library (source code is in directory 1766 <computeroutput>sdk/bindings/c/glue</computeroutput>, to be used in 1767 your API client code) to open the C binding layer during runtime, 1768 which is preferred to other means as it isolates the code which 1769 locates the necessary dynamic library, using a known working way 1770 which works on all platforms. If you encounter problems with this 1771 glue code in <computeroutput>VBoxCAPIGlue.c</computeroutput>, let the 1772 VirtualBox developers know, rather than inventing incompatible 1773 solutions.</para> 1774 1775 <para>The following sections document the important concepts needed 1776 to correctly use the C binding, as it is vital for developing API 1777 client code which manages memory correctly, updates the reference 1778 counters correctly, avoiding crashes and memory leaks. Concepts such 1779 as event handling are described in the API specification (see 1780 <xref linkend="events" />) in great detail detail, and the sample 1781 illustrates the practical aspects of how to use both types of event 1782 handling, active and passive, from a C application. If you look at 1783 the code complexity of active event handling (and its inherenly 1784 platform/compiler specific elements) it should be clear that passive 1785 event handling should be used whereever possible.</para> 1756 1786 </sect3> 1757 1787 1758 1788 <sect3 id="c-initialization"> 1759 <title>XPCOM initialization</title> 1760 1761 <para>Just like in C++, XPCOM needs to be initialized before it can 1762 be used. The <computeroutput>VBoxCAPI_v4_3.h</computeroutput> header 1763 provides the interface to the C binding. Here's how to initialize 1764 XPCOM:</para> 1765 1766 <screen>#include "VBoxCAPI_v4_3.h" 1789 <title>VirtualBox C API initialization</title> 1790 1791 <para>Just like in C++, the API and the underlying middleware needs 1792 to be initialized before it can be used. The 1793 <computeroutput>VBoxCAPI_v4_3.h</computeroutput> header provides the 1794 interface to the C binding, but you can alternatively and more 1795 conveniently also include <computeroutput>VBoxCAPIGlue.h</computeroutput>, 1796 as this avoids the VirtualBox version dependent header file name and 1797 makes sure the global variable <code>g_pVBoxFuncs</code> contains a 1798 pointer to the structure which contains the helper function pointers. 1799 Here's how to initialize the C API:<screen>#include "VBoxCAPIGlue.h" 1767 1800 ... 1768 PCVBOXXPCOM g_pVBoxFuncs = NULL; 1769 IVirtualBox *vbox = NULL; 1770 ISession *session = NULL; 1801 IVirtualBoxClient *vboxclient = NULL; 1802 IVirtualBox *vbox = NULL; 1803 ISession *session = NULL; 1804 HRESULT rc; 1805 ULONG revision; 1771 1806 1772 1807 /* 1773 * VBoxGetXPCOMCFunctions() is the only function exported by 1774 * VBoxXPCOMC.so and the only one needed to make virtualbox 1775 * work with C. This functions gives you the pointer to the 1776 * function table (g_pVBoxFuncs). 1808 * VBoxCGlueInit() loads the necessary dynamic library, handles errors 1809 * (producing an error message hinting what went wrong) and gives you 1810 * the pointer to the function table (g_pVBoxFuncs). 1777 1811 * 1778 1812 * Once you get the function table, then how and which functions 1779 1813 * to use is explained below. 1780 1814 * 1781 * g_pVBoxFuncs->pfnC omInitialize does all the necessary startup1782 * action and provides us with pointers to vbox and session handles.1783 * It should be matched by a call to g_pVBoxFuncs->pfnC omUninitialize()1815 * g_pVBoxFuncs->pfnClientInitialize does all the necessary startup 1816 * action and provides us with pointers to an IVirtualBoxClient instance. 1817 * It should be matched by a call to g_pVBoxFuncs->pfnClientUninitialize() 1784 1818 * when done. 1785 1819 */ 1786 1820 1787 g_pVBoxFuncs = VBoxGetXPCOMCFunctions(VBOX_XPCOMC_VERSION); 1788 g_pVBoxFuncs->pfnComInitialize(IVIRTUALBOX_IID_STR, &vbox, 1789 ISESSION_IID_STR, &session);</screen> 1790 1791 <para>If either <computeroutput>vbox</computeroutput> or 1792 <computeroutput>session</computeroutput> is still 1793 <computeroutput>NULL</computeroutput>, initialization failed and the 1794 XPCOM API cannot be used.</para> 1795 1796 <para>There is now also a way to use the 1797 <xref linkend="IVirtualBoxClient" xreflabel="IVirtualBoxClient" /> 1798 helper interface, which in comparison to the original (and still 1799 available) initialization method above simplifies creating multiple 1800 sessions, and also allows handling termination and crashes of the API 1801 server (VBoxSVC) in a graceful way. See the sample program how this 1802 is used.</para> 1821 if (VBoxCGlueInit()) 1822 { 1823 fprintf(stderr, "s: FATAL: VBoxCGlueInit failed: %s\n", 1824 argv[0], g_szVBoxErrMsg); 1825 return EXIT_FAILURE; 1826 } 1827 1828 g_pVBoxFuncs->pfnClientInitialize(NULL, &vboxclient); 1829 if (!vboxclient) 1830 { 1831 fprintf(stderr, "%s: FATAL: could not get VirtualBoxClient reference\n", 1832 argv[0]); 1833 return EXIT_FAILURE; 1834 }</screen></para> 1835 1836 <para>If <computeroutput>vboxclient</computeroutput> is still 1837 <computeroutput>NULL</computeroutput> this means the initializationi 1838 failed and the VirtualBox C API cannot be used.</para> 1839 1840 <para>It is possible to write C applications using multiple threads 1841 which all use the VirtualBox API, as long as you're initializing 1842 the C API in each thread which your application creates. This is done 1843 with <code>g_pVBoxFuncs->pfnClientThreadInitialize()</code> and 1844 likewise before the thread is terminated the API must be 1845 uninitialized with 1846 <code>g_pVBoxFuncs->pfnClientThreadUninitialize()</code>. You don't 1847 have to use these functions in worker threads created by COM/XPCOM 1848 (which you might observe if your code uses active event handling), 1849 everything is initialized correctly already. On Windows the C 1850 bindings create a marshaller which supports a wide range of COM 1851 threading models, from STA to MTA, so you don't have to worry about 1852 these details unless you plan to use active event handlers. See 1853 the sample code how to get this to work reliably (in other words 1854 think twice if passive event handling isn't the better solution after 1855 you looked at the sample code).</para> 1803 1856 </sect3> 1804 1857 1805 1858 <sect3 id="c-invocation"> 1806 <title> XPCOMmethod invocation</title>1859 <title>C API attribute and method invocation</title> 1807 1860 1808 1861 <para>Method invocation is straightforward. It looks pretty much 1809 like the C++ way, augmented with an extra indirection due to1810 accessing the vtable and passing a pointer to the object as the1811 first argument to serve as the <computeroutput>this</computeroutput>1812 pointer.</para>1862 like the C++ way, by using a macro which internally accesses the 1863 vtable, and additionally needs to be passed a pointer to the objecti 1864 as the first argument to serve as the 1865 <computeroutput>this</computeroutput> pointer.</para> 1813 1866 1814 1867 <para>Using the C binding, all method invocations return a numeric 1815 result code.</para> 1868 result code of type <code>HRESULT</code> (with a few exceptions 1869 which normally are not relevant).</para> 1816 1870 1817 1871 <para>If an interface is specified as returning an object, a pointer … … 1820 1874 location.</para> 1821 1875 1822 <para>In other words, to call an object's method what you need 1823 is</para> 1824 1825 <screen>IObject *object; 1826 nsresult rc; 1876 <para>Likewise, attributes (properties) can be queried or set using 1877 method invocations, using specially named methods. For each 1878 attribute there exists a getter method, the name of which is composed 1879 of <computeroutput>get_</computeroutput> followed by the capitalized 1880 attribute name. Unless the attribute is read-only, an analogous 1881 <computeroutput>set_</computeroutput> method exists. Let's apply 1882 these rules to get the <computeroutput>IVirtualBox</computeroutput> 1883 reference, an <computeroutput>ISession</computeroutput> instance 1884 reference and read the <xref linkend="IVirtualBox__revision" 1885 xreflabel="IVirtualBox::revision" /> attribute:<screen>rc = IVirtualBoxClient_get_VirtualBox(vboxclient, &vbox); 1886 if (FAILED(rc) || !vbox) 1887 { 1888 PrintErrorInfo(argv[0], "FATAL: could not get VirtualBox reference", rc); 1889 return EXIT_FAILURE; 1890 } 1891 rc = IVirtualBoxClient_get_Session(vboxclient, &session); 1892 if (FAILED(rc) || !session) 1893 { 1894 PrintErrorInfo(argv[0], "FATAL: could not get Session reference", rc); 1895 return EXIT_FAILURE; 1896 } 1897 1898 rc = IVirtualBox_get_Revision(vbox, &revision); 1899 if (SUCCEEDED(rc)) 1900 { 1901 printf("Revision: %u\n", revision); 1902 }</screen></para> 1903 1904 <para>The convenience macros for calling a method are named by 1905 prepending the method name with the interface name (using 1906 <code>_</code>as the separator).</para> 1907 1908 <para>So far only attribute getters were illustrated, but generic 1909 method calls are straightforward, too:<screen>IMachine *machine = NULL; 1910 BSTR vmname = ...; 1827 1911 ... 1828 1912 /* 1829 * Calling void IObject::method(arg,...)1913 * Calling IMachine::findMachine(...) 1830 1914 */ 1831 rc = object->vtbl->Method(object, arg, ...); 1832 1833 ... 1834 IFoo *foo; 1835 /* 1836 * Calling IFoo IObject::method(arg, ...) 1837 */ 1838 rc = object->vtbl->Method(object, args, ..., &foo);</screen> 1839 1840 <para>As a real-world example of a method invocation, let's call 1841 <xref linkend="IMachine__launchVMProcess" 1915 rc = IVirtualBox_FindMachine(vbox, vmname, &machine);</screen></para> 1916 1917 <para>As a more complicated example of a method invocation, let's 1918 call <xref linkend="IMachine__launchVMProcess" 1842 1919 xreflabel="IMachine::launchVMProcess" /> which returns an 1843 1920 IProgress object. Note again that the method name is 1844 capitalized.</para> 1845 1846 <screen>IProgress *progress; 1921 capitalized:<screen>IProgress *progress; 1847 1922 ... 1848 rc = vbox->vtbl->LaunchVMProcess(1923 rc = IMachine_LaunchVMProcess( 1849 1924 machine, /* this */ 1850 1925 session, /* arg 1 */ … … 1852 1927 env, /* arg 3 */ 1853 1928 &progress /* Out */ 1854 );</screen> 1855 </sect3> 1856 1857 <sect3 id="c-attributes"> 1858 <title>XPCOM attribute access</title> 1859 1860 <para>A construct similar to calling non-void methods is used to 1861 access object attributes. For each attribute there exists a getter 1862 method, the name of which is composed of 1863 <computeroutput>Get</computeroutput> followed by the capitalized 1864 attribute name. Unless the attribute is read-only, an analogous 1865 <computeroutput>Set</computeroutput> method exists. Let's apply 1866 these rules to read the <xref linkend="IVirtualBox__revision" 1867 xreflabel="IVirtualBox::revision" /> attribute.</para> 1868 1869 <para>Using the <computeroutput>IVirtualBox</computeroutput> handle 1870 <computeroutput>vbox</computeroutput> obtained above, calling its 1871 <computeroutput>GetRevision</computeroutput> method looks like 1872 this:</para> 1873 1874 <screen>PRUint32 rev; 1875 1876 rc = vbox->vtbl->GetRevision(vbox, &rev); 1877 if (NS_SUCCEEDED(rc)) 1878 { 1879 printf("Revision: %u\n", (unsigned)rev); 1880 }</screen> 1929 );</screen></para> 1881 1930 1882 1931 <para>All objects with their methods and attributes are documented … … 1890 1939 encoding and ownership.</para> 1891 1940 1892 <para>Internally, XPCOMuses UTF-16 encoded strings. A set of1941 <para>Internally, the API uses UTF-16 encoded strings. A set of 1893 1942 conversion functions is provided to convert other encodings to and 1894 1943 from UTF-16. The type of a UTF-16 character is 1895 <computeroutput>PRUnichar</computeroutput>. Strings of UTF-16 1896 characters are arrays of that type. Most string handling functions 1897 take pointers to that type. Prototypes for the following conversion 1898 functions are declared in 1899 <computeroutput>VBoxCAPI_v4_3.h</computeroutput>.</para> 1900 1901 <sect4> 1902 <title>Conversion of UTF-16 to and from UTF-8</title> 1903 1904 <screen>int (*pfnUtf16ToUtf8)(const PRUnichar *pwszString, char **ppszString); 1905 int (*pfnUtf8ToUtf16)(const char *pszString, PRUnichar **ppwszString);</screen> 1906 </sect4> 1907 1908 <sect4> 1909 <title>Ownership</title> 1910 1911 <para>The ownership of a string determines who is responsible for 1912 releasing resources associated with the string. Whenever XPCOM 1913 creates a string, ownership is transferred to the caller. To avoid 1914 resource leaks, the caller should release resources once the 1915 string is no longer needed.</para> 1916 </sect4> 1944 <computeroutput>BSTR</computeroutput> (or its constant counterpart 1945 <computeroutput>CBSTR</computeroutput>), which is an array type, 1946 represented by a pointer to the start of the zero-terminated string. 1947 There are functions for converting between UTF-8 and UTF-16 strings 1948 available through <code>g_pVBoxFuncs</code>:<screen>int (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString); 1949 int (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);</screen></para> 1950 1951 <para>The ownership of a string determines who is responsible for 1952 releasing resources associated with the string. Whenever the API 1953 creates a string (essentially for output parameters), ownership is 1954 transferred to the caller. To avoid resource leaks, the caller 1955 should release resources once the string is no longer needed. 1956 There are plenty of examples in the sample code.</para> 1917 1957 </sect3> 1918 1958 1959 <sect3 id="c-safearray"> 1960 <title>Array handling</title> 1961 1962 <para>Arrays are handled somewhat similarly to strings, with the 1963 additional information of the number of elements in the array. The 1964 exact details of string passing depends on the platform middleware 1965 (COM/XPCOM), and therefore the C binding offers helper functions to 1966 gloss over these differences.</para> 1967 1968 <para>Passing arrays as input parameters to API methods is usually 1969 done by the following sequence, calling a hypothetical 1970 <code>IArrayDemo_PassArray</code> API method:<screen>static const ULONG aElements[] = { 1, 2, 3, 4 }; 1971 ULONG cElements = sizeof(aElements) / sizeof(aElements[0]); 1972 SAFEARRAY *psa = NULL; 1973 psa = g_pVBoxFuncs->pfnSafeArrayCreateVector(VT_I4, 0, cElements); 1974 g_pVBoxFuncs->pfnSafeArrayCopyInParamHelper(psa, aElements, sizeof(aElements)); 1975 IArrayDemo_PassArray(pThis, ComSafeArrayAsInParam(psa)); 1976 g_pVBoxFuncs->pfnSafeArrayDestroy(psa);</screen></para> 1977 1978 <para>Likewise, getting arrays results from output parameters is done 1979 using helper functions which manage memory allocations as part of 1980 their other functionality:<screen>SAFEARRAY *psa = g_pVBoxFuncs->pfnSafeArrayOutParamAlloc(); 1981 ULONG *pData; 1982 ULONG cElements; 1983 IArrayDemo_ReturnArray(pThis, ComSafeArrayAsOutParam(psa)); 1984 g_pVBoxFuncs->pfnSafeArrayCopyOutParamHelper((void **)&pData, &cElements, VT_I4, psa); 1985 g_pVBoxFuncs->pfnSafeArrayDestroy(psa);</screen></para> 1986 1987 <para>This covers the necessary functionality for all array element 1988 types except interface references. These need special helpers to 1989 manage the reference counting correctly. The following code snippet 1990 gets the list of VMs, and passes the first IMachine reference to 1991 another API function (assuming that there is at least one element 1992 in the array, to simplify the example):<screen>SAFEARRAY psa = g_pVBoxFuncs->pfnSafeArrayOutParamAlloc(); 1993 IMachine **machines = NULL; 1994 ULONG machineCnt = 0; 1995 ULONG i; 1996 IVirtualBox_get_Machines(virtualBox, ComSafeArrayAsOutIfaceParam(machinesSA, IMachine *)); 1997 g_pVBoxFuncs->pfnSafeArrayCopyOutIfaceParamHelper((IUnknown ***)&machines, &machineCnt, machinesSA); 1998 g_pVBoxFuncs->pfnSafeArrayDestroy(machinesSA); 1999 /* Now "machines" contains the IMachine references, and machineCnt the 2000 * number of elements in the array. */ 2001 ... 2002 SAFEARRAY *psa = g_pVBoxFuncs->pfnSafeArrayCreateVector(VT_IUNKNOWN, 0, 1); 2003 g_pVBoxFuncs->pfnSafeArrayCopyInParamHelper(psa, (void *)&machines[0], sizeof(machines[0])); 2004 IVirtualBox_GetMachineStates(ComSafeArrayAsInParam(psa), ...); 2005 ... 2006 g_pVBoxFuncs->pfnSafeArrayDestroy(psa); 2007 for (i = 0; i < machineCnt; ++i) 2008 { 2009 IMachine *machine = machines[i]; 2010 IMachine_Release(machine); 2011 } 2012 free(machines);</screen></para> 2013 2014 <para>Handling output parameters needs more special effort than 2015 input parameters, thus only for the former there are special helpers, 2016 and the latter is handled through the generic array support.</para> 2017 </sect3> 2018 1919 2019 <sect3 id="c-uninitialization"> 1920 <title> XPCOMuninitialization</title>2020 <title>C API uninitialization</title> 1921 2021 1922 2022 <para>Uninitialization is performed by 1923 <computeroutput>g_pVBoxFuncs->pfnC omUninitialize().</computeroutput>2023 <computeroutput>g_pVBoxFuncs->pfnClientUninitialize().</computeroutput> 1924 2024 If your program can exit from more than one place, it is a good idea 1925 2025 to install this function as an exit handler with Standard C's 1926 2026 <computeroutput>atexit()</computeroutput> just after calling 1927 <computeroutput>g_pVBoxFuncs->pfnC omInitialize()</computeroutput>2027 <computeroutput>g_pVBoxFuncs->pfnClientInitialize()</computeroutput> 1928 2028 , e.g. <screen>#include <stdlib.h> 1929 2029 #include <stdio.h> … … 1932 2032 1933 2033 /* 1934 * Make sure g_pVBoxFuncs->pfnC omUninitialize() is called at exit, no2034 * Make sure g_pVBoxFuncs->pfnClientUninitialize() is called at exit, no 1935 2035 * matter if we return from the initial call to main or call exit() 1936 2036 * somewhere else. Note that atexit registered functions are not 1937 2037 * called upon abnormal termination, i.e. when calling abort() or 1938 * signal(). Separate provisions must be taken for these cases.2038 * signal(). 1939 2039 */ 1940 2040 1941 if (atexit(g_pVBoxFuncs->pfnC omUninitialize()) != 0) {1942 fprintf(stderr, "failed to register g_pVBoxFuncs->pfnC omUninitialize()\n");2041 if (atexit(g_pVBoxFuncs->pfnClientUninitialize()) != 0) { 2042 fprintf(stderr, "failed to register g_pVBoxFuncs->pfnClientUninitialize()\n"); 1943 2043 exit(EXIT_FAILURE); 1944 2044 }</screen></para> … … 1946 2046 <para>Another idea would be to write your own <computeroutput>void 1947 2047 myexit(int status)</computeroutput> function, calling 1948 <computeroutput>g_pVBoxFuncs->pfnC omUninitialize()</computeroutput>2048 <computeroutput>g_pVBoxFuncs->pfnClientUninitialize()</computeroutput> 1949 2049 followed by the real <computeroutput>exit()</computeroutput>, and 1950 2050 use it instead of <computeroutput>exit()</computeroutput> throughout … … 1956 2056 handler setting a flag noting that a signal was sent and then 1957 2057 calling 1958 <computeroutput>g_pVBoxFuncs->pfnC omUninitialize()</computeroutput>2058 <computeroutput>g_pVBoxFuncs->pfnClientUninitialize()</computeroutput> 1959 2059 later on, <emphasis>not</emphasis> from the handler itself.</para> 1960 2060 1961 2061 <para>That said, if a client program forgets to call 1962 <computeroutput>g_pVBoxFuncs->pfnC omUninitialize()</computeroutput>2062 <computeroutput>g_pVBoxFuncs->pfnClientUninitialize()</computeroutput> 1963 2063 before it terminates, there is a mechanism in place which will 1964 eventually release references held by the client.</para> 2064 eventually release references held by the client. On Windows it can 2065 take quite a while, in the order of 6-7 minutes.</para> 1965 2066 </sect3> 1966 2067 … … 1970 2071 <para>A program using the C binding has to open the library during 1971 2072 runtime using the help of glue code provided and as shown in the 1972 example <computeroutput>tstXPCOMCGlue.c</computeroutput>. 1973 Compilation and linking can be achieved, e.g., with a makefile 1974 fragment similar to</para> 1975 1976 <screen># Where is the XPCOM include directory? 1977 INCS_XPCOM = -I../../include 1978 # Where is the glue code directory? 1979 GLUE_DIR = .. 1980 GLUE_INC = -I.. 1981 1982 #Compile Glue Library 1983 VBoxXPCOMCGlue.o: $(GLUE_DIR)/VBoxXPCOMCGlue.c 1984 $(CC) $(CFLAGS) $(INCS_XPCOM) $(GLUE_INC) -o $@ -c $< 1985 1986 # Compile. 1987 program.o: program.c VBoxCAPI_v4_3.h 1988 $(CC) $(CFLAGS) $(INCS_XPCOM) $(GLUE_INC) -o $@ -c $< 1989 1990 # Link. 1991 program: program.o VBoxXPCOMCGlue.o 1992 $(CC) -o $@ $^ -ldl</screen> 2073 example <computeroutput>tstCAPIGlue.c</computeroutput>. 2074 Compilation and linking can be achieved with a makefile fragment 2075 similar to:<screen># Where is the SDK directory? 2076 PATH_SDK = ../../.. 2077 CAPI_INC = -I$(PATH_SDK)/bindings/c/include 2078 ifeq ($(BUILD_PLATFORM),win) 2079 PLATFORM_INC = -I$(PATH_SDK)/bindings/mscom/include 2080 PLATFORM_LIB = $(PATH_SDK)/bindings/mscom/lib 2081 else 2082 PLATFORM_INC = -I$(PATH_SDK)/bindings/xpcom/include 2083 PLATFORM_LIB = $(PATH_SDK)/bindings/xpcom/lib 2084 endif 2085 GLUE_DIR = $(PATH_SDK)/bindings/c/glue 2086 GLUE_INC = -I$(GLUE_DIR) 2087 2088 # Compile Glue Library 2089 VBoxCAPIGlue.o: $(GLUE_DIR)/VBoxCAPIGlue.c 2090 $(CC) $(CFLAGS) $(CAPI_INC) $(PLATFORM_INC) $(GLUE_INC) -o $@ -c $< 2091 2092 # Compile interface ID list 2093 VirtualBox_i.o: $(PLATFORM_LIB)/VirtualBox_i.c 2094 $(CC) $(CFLAGS) $(CAPI_INC) $(PLATFORM_INC) $(GLUE_INC) -o $@ -c $< 2095 2096 # Compile program code 2097 program.o: program.c 2098 $(CC) $(CFLAGS) $(CAPI_INC) $(PLATFORM_INC) $(GLUE_INC) -o $@ -c $< 2099 2100 # Link program. 2101 program: program.o VBoxCAPICGlue.o VirtualBox_i.o 2102 $(CC) -o $@ $^ -ldl -lpthread</screen></para> 2103 </sect3> 2104 2105 <sect3 id="capi_conversion"> 2106 <title>Conversion of code using legacy C binding</title> 2107 2108 <para>This section aims to make the task of converting code using 2109 the legacy C binding to the new style a breeze, by pointing out some 2110 key steps.</para> 2111 2112 <para>One necessary change is adjusting your Makefile to reflect the 2113 different include paths. See above. There are now 3 relevant include 2114 directories, and most of it is pointing to the C binding directory. 2115 The XPCOM include directory is still relevant for platforms where 2116 the XPCOM middleware is used, but most of the include files live 2117 elsewhere now, so it's good to have it last. Additionally the 2118 <computeroutput>VirtualBox_i.c</computeroutput> file needs to be 2119 compiled and linked to the program, it contains the IIDs relevant 2120 for the VirtualBox API, making sure they are not replicated endlessly 2121 if the code refers to them frequently.</para> 2122 2123 <para>The C API client code should include <computeroutput>VBoxCAPIGlue.h</computeroutput> 2124 instead of <computeroutput>VBoxXPCOMCGlue.h</computeroutput> or 2125 <computeroutput>VBoxCAPI_v4_3.h</computeroutput>, as this makes sure 2126 the correct macros and internal translations are selected.</para> 2127 2128 <para>All API method calls (anything mentioning <code>vtbl</code>) 2129 should be rewritten using the convenience macros for calling methods, 2130 as these hide the internal details, are generally easier to use and 2131 shorter to type. You should remove as many as possible 2132 <code>(nsISupports **)</code> or similar typecasts, as the new style 2133 should use the correct type in most places, increasing the type 2134 safety in case of an error in the source code.</para> 2135 2136 <para>Finally adjust the string and array handling to use the new 2137 helpers, as these make sure the code works without changes with 2138 both COM and XPCOM, which are significantly different in this area. 2139 The code should be double checked if it uses the correct way to 2140 manage memory, and is freeing it only after the last use.</para> 2141 </sect3> 2142 2143 <sect3 id="xpcom_cbinding"> 2144 <title>Legacy C binding to VirtualBox API for XPCOM</title> 2145 2146 <note> 2147 <para>This section applies to Linux, Mac OS X and Solaris 2148 hosts only and describes deprecated use of the API from C.</para> 2149 </note> 2150 2151 <para>Starting with version 2.2, VirtualBox offers a C binding for 2152 its API which works only on platforms using XPCOM. Refer to the 2153 old SDK documentation, it still applies unchanged. The fundamental 2154 concepts are similar (but the syntactical details are quite 2155 different) to the newer cross-platform C binding which should be 2156 used for all new code, as the support for the old C binding will go 2157 away in a major release after version 4.3.</para> 1993 2158 </sect3> 1994 2159 </sect2> … … 2139 2304 </sect1> 2140 2305 2141 <sect1 >2306 <sect1 id="events"> 2142 2307 <title>VirtualBox events</title> 2143 2308
Note:
See TracChangeset
for help on using the changeset viewer.