VirtualBox

Changeset 50262 in vbox for trunk


Ignore:
Timestamp:
Jan 28, 2014 4:52:15 PM (11 years ago)
Author:
vboxsync
Message:

doc/manual/en_US/SDKRef.xml: document new style C API binding

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/doc/manual/en_US/SDKRef.xml

    r49525 r50262  
    17191719
    17201720      <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>
    17331739
    17341740        <sect3 id="c-gettingstarted">
    17351741          <title>Getting started</title>
    17361742
    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
    17421753          VirtualBox and Session objects, make calls to list and start virtual
    17431754          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>
    17561786        </sect3>
    17571787
    17581788        <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"
    17671800...
    1768 PCVBOXXPCOM g_pVBoxFuncs = NULL;
    1769 IVirtualBox *vbox        = NULL;
    1770 ISession *session        = NULL;
     1801IVirtualBoxClient *vboxclient   = NULL;
     1802IVirtualBox *vbox               = NULL;
     1803ISession *session               = NULL;
     1804HRESULT rc;
     1805ULONG revision;
    17711806
    17721807/*
    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).
    17771811 *
    17781812 * Once you get the function table, then how and which functions
    17791813 * to use is explained below.
    17801814 *
    1781  * g_pVBoxFuncs-&gt;pfnComInitialize does all the necessary startup
    1782  * action and provides us with pointers to vbox and session handles.
    1783  * It should be matched by a call to g_pVBoxFuncs-&gt;pfnComUninitialize()
     1815 * g_pVBoxFuncs-&gt;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-&gt;pfnClientUninitialize()
    17841818 * when done.
    17851819 */
    17861820
    1787 g_pVBoxFuncs = VBoxGetXPCOMCFunctions(VBOX_XPCOMC_VERSION);
    1788 g_pVBoxFuncs-&gt;pfnComInitialize(IVIRTUALBOX_IID_STR, &amp;vbox,
    1789                                ISESSION_IID_STR, &amp;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>
     1821if (VBoxCGlueInit())
     1822{
     1823    fprintf(stderr, "s: FATAL: VBoxCGlueInit failed: %s\n",
     1824            argv[0], g_szVBoxErrMsg);
     1825    return EXIT_FAILURE;
     1826}
     1827   
     1828g_pVBoxFuncs-&gt;pfnClientInitialize(NULL, &amp;vboxclient);
     1829if (!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>
    18031856        </sect3>
    18041857
    18051858        <sect3 id="c-invocation">
    1806           <title>XPCOM method invocation</title>
     1859          <title>C API attribute and method invocation</title>
    18071860
    18081861          <para>Method invocation is straightforward. It looks pretty much
    1809           like the C++ way, augmented with an extra indirection due to
    1810           accessing the vtable and passing a pointer to the object as the
    1811           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>
    18131866
    18141867          <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>
    18161870
    18171871          <para>If an interface is specified as returning an object, a pointer
     
    18201874          location.</para>
    18211875
    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, &amp;vbox);
     1886if (FAILED(rc) || !vbox)
     1887{
     1888    PrintErrorInfo(argv[0], "FATAL: could not get VirtualBox reference", rc);
     1889    return EXIT_FAILURE;
     1890}
     1891rc = IVirtualBoxClient_get_Session(vboxclient, &amp;session);
     1892if (FAILED(rc) || !session)
     1893{
     1894    PrintErrorInfo(argv[0], "FATAL: could not get Session reference", rc);
     1895    return EXIT_FAILURE;
     1896}
     1897
     1898rc = IVirtualBox_get_Revision(vbox, &amp;revision);
     1899if (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;
     1910BSTR vmname = ...;
    18271911...
    18281912/*
    1829  * Calling void IObject::method(arg, ...)
     1913 * Calling IMachine::findMachine(...)
    18301914 */
    1831 rc = object-&gt;vtbl-&gt;Method(object, arg, ...);
    1832 
    1833 ...
    1834 IFoo *foo;
    1835 /*
    1836  * Calling IFoo IObject::method(arg, ...)
    1837  */
    1838 rc = object-&gt;vtbl-&gt;Method(object, args, ..., &amp;foo);</screen>
    1839 
    1840           <para>As a real-world example of a method invocation, let's call
    1841           <xref linkend="IMachine__launchVMProcess"
     1915rc = IVirtualBox_FindMachine(vbox, vmname, &amp;machine);</screen></para>
     1916
     1917          <para>As a more complicated example of a method invocation, let's
     1918          call <xref linkend="IMachine__launchVMProcess"
    18421919          xreflabel="IMachine::launchVMProcess" /> which returns an
    18431920          IProgress object. Note again that the method name is
    1844           capitalized.</para>
    1845 
    1846           <screen>IProgress *progress;
     1921          capitalized:<screen>IProgress *progress;
    18471922...
    1848 rc = vbox-&gt;vtbl-&gt;LaunchVMProcess(
     1923rc = IMachine_LaunchVMProcess(
    18491924    machine,       /* this  */
    18501925    session,       /* arg 1 */
     
    18521927    env,           /* arg 3 */
    18531928    &amp;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-&gt;vtbl-&gt;GetRevision(vbox, &amp;rev);
    1877 if (NS_SUCCEEDED(rc))
    1878 {
    1879     printf("Revision: %u\n", (unsigned)rev);
    1880 }</screen>
     1929);</screen></para>
    18811930
    18821931          <para>All objects with their methods and attributes are documented
     
    18901939          encoding and ownership.</para>
    18911940
    1892           <para>Internally, XPCOM uses UTF-16 encoded strings. A set of
     1941          <para>Internally, the API uses UTF-16 encoded strings. A set of
    18931942          conversion functions is provided to convert other encodings to and
    18941943          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);
     1949int (*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>
    19171957        </sect3>
    19181958
     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 };
     1971ULONG cElements = sizeof(aElements) / sizeof(aElements[0]);
     1972SAFEARRAY *psa = NULL;
     1973psa = g_pVBoxFuncs->pfnSafeArrayCreateVector(VT_I4, 0, cElements);
     1974g_pVBoxFuncs->pfnSafeArrayCopyInParamHelper(psa, aElements, sizeof(aElements));
     1975IArrayDemo_PassArray(pThis, ComSafeArrayAsInParam(psa));
     1976g_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();
     1981ULONG *pData;
     1982ULONG cElements;
     1983IArrayDemo_ReturnArray(pThis, ComSafeArrayAsOutParam(psa));
     1984g_pVBoxFuncs->pfnSafeArrayCopyOutParamHelper((void **)&amp;pData, &amp;cElements, VT_I4, psa);
     1985g_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();
     1993IMachine **machines = NULL;
     1994ULONG machineCnt = 0;
     1995ULONG i;
     1996IVirtualBox_get_Machines(virtualBox, ComSafeArrayAsOutIfaceParam(machinesSA, IMachine *));
     1997g_pVBoxFuncs->pfnSafeArrayCopyOutIfaceParamHelper((IUnknown ***)&amp;machines, &amp;machineCnt, machinesSA);
     1998g_pVBoxFuncs->pfnSafeArrayDestroy(machinesSA);
     1999/* Now "machines" contains the IMachine references, and machineCnt the
     2000 * number of elements in the array. */
     2001...
     2002SAFEARRAY *psa = g_pVBoxFuncs->pfnSafeArrayCreateVector(VT_IUNKNOWN, 0, 1);
     2003g_pVBoxFuncs->pfnSafeArrayCopyInParamHelper(psa, (void *)&amp;machines[0], sizeof(machines[0]));
     2004IVirtualBox_GetMachineStates(ComSafeArrayAsInParam(psa), ...);
     2005...
     2006g_pVBoxFuncs->pfnSafeArrayDestroy(psa);
     2007for (i = 0; i &lt; machineCnt; ++i)
     2008{
     2009    IMachine *machine = machines[i];
     2010    IMachine_Release(machine);
     2011}
     2012free(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
    19192019        <sect3 id="c-uninitialization">
    1920           <title>XPCOM uninitialization</title>
     2020          <title>C API uninitialization</title>
    19212021
    19222022          <para>Uninitialization is performed by
    1923           <computeroutput>g_pVBoxFuncs-&gt;pfnComUninitialize().</computeroutput>
     2023          <computeroutput>g_pVBoxFuncs-&gt;pfnClientUninitialize().</computeroutput>
    19242024          If your program can exit from more than one place, it is a good idea
    19252025          to install this function as an exit handler with Standard C's
    19262026          <computeroutput>atexit()</computeroutput> just after calling
    1927           <computeroutput>g_pVBoxFuncs-&gt;pfnComInitialize()</computeroutput>
     2027          <computeroutput>g_pVBoxFuncs-&gt;pfnClientInitialize()</computeroutput>
    19282028          , e.g. <screen>#include &lt;stdlib.h&gt;
    19292029#include &lt;stdio.h&gt;
     
    19322032
    19332033/*
    1934  * Make sure g_pVBoxFuncs-&gt;pfnComUninitialize() is called at exit, no
     2034 * Make sure g_pVBoxFuncs-&gt;pfnClientUninitialize() is called at exit, no
    19352035 * matter if we return from the initial call to main or call exit()
    19362036 * somewhere else. Note that atexit registered functions are not
    19372037 * called upon abnormal termination, i.e. when calling abort() or
    1938  * signal(). Separate provisions must be taken for these cases.
     2038 * signal().
    19392039 */
    19402040
    1941 if (atexit(g_pVBoxFuncs-&gt;pfnComUninitialize()) != 0) {
    1942     fprintf(stderr, "failed to register g_pVBoxFuncs-&gt;pfnComUninitialize()\n");
     2041if (atexit(g_pVBoxFuncs-&gt;pfnClientUninitialize()) != 0) {
     2042    fprintf(stderr, "failed to register g_pVBoxFuncs-&gt;pfnClientUninitialize()\n");
    19432043    exit(EXIT_FAILURE);
    19442044}</screen></para>
     
    19462046          <para>Another idea would be to write your own <computeroutput>void
    19472047          myexit(int status)</computeroutput> function, calling
    1948           <computeroutput>g_pVBoxFuncs-&gt;pfnComUninitialize()</computeroutput>
     2048          <computeroutput>g_pVBoxFuncs-&gt;pfnClientUninitialize()</computeroutput>
    19492049          followed by the real <computeroutput>exit()</computeroutput>, and
    19502050          use it instead of <computeroutput>exit()</computeroutput> throughout
     
    19562056          handler setting a flag noting that a signal was sent and then
    19572057          calling
    1958           <computeroutput>g_pVBoxFuncs-&gt;pfnComUninitialize()</computeroutput>
     2058          <computeroutput>g_pVBoxFuncs-&gt;pfnClientUninitialize()</computeroutput>
    19592059          later on, <emphasis>not</emphasis> from the handler itself.</para>
    19602060
    19612061          <para>That said, if a client program forgets to call
    1962           <computeroutput>g_pVBoxFuncs-&gt;pfnComUninitialize()</computeroutput>
     2062          <computeroutput>g_pVBoxFuncs-&gt;pfnClientUninitialize()</computeroutput>
    19632063          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>
    19652066        </sect3>
    19662067
     
    19702071          <para>A program using the C binding has to open the library during
    19712072          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 $&lt;
    1985 
    1986 # Compile.
    1987 program.o: program.c VBoxCAPI_v4_3.h
    1988     $(CC) $(CFLAGS) $(INCS_XPCOM) $(GLUE_INC) -o $@ -c $&lt;
    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?
     2076PATH_SDK      = ../../..
     2077CAPI_INC      = -I$(PATH_SDK)/bindings/c/include
     2078ifeq ($(BUILD_PLATFORM),win)
     2079PLATFORM_INC  = -I$(PATH_SDK)/bindings/mscom/include
     2080PLATFORM_LIB  = $(PATH_SDK)/bindings/mscom/lib
     2081else
     2082PLATFORM_INC  = -I$(PATH_SDK)/bindings/xpcom/include
     2083PLATFORM_LIB  = $(PATH_SDK)/bindings/xpcom/lib
     2084endif
     2085GLUE_DIR      = $(PATH_SDK)/bindings/c/glue
     2086GLUE_INC      = -I$(GLUE_DIR)
     2087
     2088# Compile Glue Library
     2089VBoxCAPIGlue.o: $(GLUE_DIR)/VBoxCAPIGlue.c
     2090    $(CC) $(CFLAGS) $(CAPI_INC) $(PLATFORM_INC) $(GLUE_INC) -o $@ -c $&lt;
     2091
     2092# Compile interface ID list
     2093VirtualBox_i.o: $(PLATFORM_LIB)/VirtualBox_i.c
     2094    $(CC) $(CFLAGS) $(CAPI_INC) $(PLATFORM_INC) $(GLUE_INC) -o $@ -c $&lt;
     2095
     2096# Compile program code
     2097program.o: program.c
     2098    $(CC) $(CFLAGS) $(CAPI_INC) $(PLATFORM_INC) $(GLUE_INC) -o $@ -c $&lt;
     2099
     2100# Link program.
     2101program: 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>
    19932158        </sect3>
    19942159      </sect2>
     
    21392304    </sect1>
    21402305
    2141     <sect1>
     2306    <sect1 id="events">
    21422307      <title>VirtualBox events</title>
    21432308
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette