<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML ><HEAD ><TITLE >The Solution</TITLE ><META NAME="GENERATOR" CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK REL="HOME" TITLE="C++ dlopen mini HOWTO" HREF="index.html"><LINK REL="PREVIOUS" TITLE="The Problem" HREF="theproblem.html"><LINK REL="NEXT" TITLE="Source Code" HREF="source.html"></HEAD ><BODY CLASS="section" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#840084" ALINK="#0000FF" ><DIV CLASS="NAVHEADER" ><TABLE SUMMARY="Header navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TH COLSPAN="3" ALIGN="center" >C++ dlopen mini HOWTO</TH ></TR ><TR ><TD WIDTH="10%" ALIGN="left" VALIGN="bottom" ><A HREF="theproblem.html" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="80%" ALIGN="center" VALIGN="bottom" ></TD ><TD WIDTH="10%" ALIGN="right" VALIGN="bottom" ><A HREF="source.html" ACCESSKEY="N" >Next</A ></TD ></TR ></TABLE ><HR ALIGN="LEFT" WIDTH="100%"></DIV ><DIV CLASS="section" ><H1 CLASS="section" ><A NAME="thesolution" ></A >3. The Solution</H1 ><DIV CLASS="section" ><H2 CLASS="section" ><A NAME="externC" ></A >3.1. <TT CLASS="literal" >extern "C"</TT ></H2 ><P >C++ has a special keyword to declare a function with C bindings: <TT CLASS="literal" >extern "C"</TT >. A function declared as <TT CLASS="literal" >extern "C"</TT > uses the function name as symbol name, just as a C function. For that reason, only non-member functions can be declared as <TT CLASS="literal" >extern "C"</TT >, and they cannot be overloaded.</P ><P >Although there are severe limitations, <TT CLASS="literal" >extern "C"</TT > functions are very useful because they can be dynamically loaded using <TT CLASS="function" >dlopen</TT > just like a C function.</P ><P >This does <EM >not</EM > mean that functions qualified as <TT CLASS="literal" >extern "C"</TT > cannot contain C++ code. Such a function is a full-featured C++ function which can use C++ features and take any type of argument.</P ></DIV ><DIV CLASS="section" ><H2 CLASS="section" ><A NAME="loadingfunctions" ></A >3.2. Loading Functions</H2 ><P >In C++ functions are loaded just like in C, with <TT CLASS="function" >dlsym</TT >. The functions you want to load must be qualified as <TT CLASS="literal" >extern "C"</TT > to avoid the symbol name being mangled.</P ><DIV CLASS="example" ><A NAME="AEN162" ></A ><P ><B >Example 1. Loading a Function</B ></P ><P >main.cpp:</P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="programlisting" >#include <iostream> #include <dlfcn.h> int main() { using std::cout; using std::cerr; cout << "C++ dlopen demo\n\n"; // open the library cout << "Opening hello.so...\n"; void* handle = dlopen("./hello.so", RTLD_LAZY); if (!handle) { cerr << "Cannot open library: " << dlerror() << '\n'; return 1; } // load the symbol cout << "Loading symbol hello...\n"; typedef void (*hello_t)(); // reset errors dlerror(); hello_t hello = (hello_t) dlsym(handle, "hello"); const char *dlsym_error = dlerror(); if (dlsym_error) { cerr << "Cannot load symbol 'hello': " << dlsym_error << '\n'; dlclose(handle); return 1; } // use it to do the calculation cout << "Calling hello...\n"; hello(); // close the library cout << "Closing library...\n"; dlclose(handle); }</PRE ></FONT ></TD ></TR ></TABLE ><P >hello.cpp:</P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="programlisting" >#include <iostream> extern "C" void hello() { std::cout << "hello" << '\n'; } </PRE ></FONT ></TD ></TR ></TABLE ></DIV ><P >The function <TT CLASS="function" >hello</TT > is defined in <TT CLASS="filename" >hello.cpp</TT >as <TT CLASS="literal" >extern "C"</TT >; it is loaded in <TT CLASS="filename" >main.cpp</TT > with the <TT CLASS="function" >dlsym</TT > call. The function must be qualified as <TT CLASS="literal" >extern "C"</TT > because otherwise we wouldn't know its symbol name.</P ><DIV CLASS="warning" ><P ></P ><TABLE CLASS="warning" WIDTH="100%" BORDER="0" ><TR ><TD WIDTH="25" ALIGN="CENTER" VALIGN="TOP" ><IMG SRC="../images/warning.gif" HSPACE="5" ALT="Warning"></TD ><TD ALIGN="LEFT" VALIGN="TOP" ><P >There are two different forms of the <TT CLASS="literal" >extern "C"</TT > declaration: <TT CLASS="literal" >extern "C"</TT > as used above, and <TT CLASS="literal" >extern "C" { … }</TT > with the declarations between the braces. The first (inline) form is a declaration with extern linkage and with C language linkage; the second only affects language linkage. The following two declarations are thus equivalent: <DIV CLASS="informalexample" ><A NAME="AEN180" ></A ><P ></P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="programlisting" >extern "C" int foo; extern "C" void bar(); </PRE ></FONT ></TD ></TR ></TABLE ><P ></P ></DIV > and <DIV CLASS="informalexample" ><A NAME="AEN182" ></A ><P ></P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="programlisting" >extern "C" { extern int foo; extern void bar(); }</PRE ></FONT ></TD ></TR ></TABLE ><P ></P ></DIV > As there is no difference between an <TT CLASS="literal" >extern</TT > and a non-<TT CLASS="literal" >extern</TT > <EM >function</EM > declaration, this is no problem as long as you are not declaring any variables. If you declare <EM >variables</EM >, keep in mind that <DIV CLASS="informalexample" ><A NAME="AEN188" ></A ><P ></P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="programlisting" >extern "C" int foo;</PRE ></FONT ></TD ></TR ></TABLE ><P ></P ></DIV > and <DIV CLASS="informalexample" ><A NAME="AEN190" ></A ><P ></P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="programlisting" >extern "C" { int foo; }</PRE ></FONT ></TD ></TR ></TABLE ><P ></P ></DIV > are <EM >not</EM > the same thing.</P ><P >For further clarifications, refer to [<SPAN CLASS="citation" >ISO14882</SPAN >], 7.5, with special attention to paragraph 7, or to [<SPAN CLASS="citation" >STR2000</SPAN >], paragraph 9.2.4.</P ><P >Before doing fancy things with extern variables, peruse the documents listed in the <A HREF="seealso.html" >see also</A > section.</P ></TD ></TR ></TABLE ></DIV ></DIV ><DIV CLASS="section" ><H2 CLASS="section" ><A NAME="loadingclasses" ></A >3.3. Loading Classes</H2 ><P >Loading classes is a bit more difficult because we need an <EM >instance</EM > of a class, not just a pointer to a function.</P ><P >We cannot create the instance of the class using <TT CLASS="literal" >new</TT > because the class is not defined in the executable, and because (under some circumstances) we don't even know its name.</P ><P >The solution is achieved through polymorphism. We define a base, <EM >interface</EM > class with virtual members <EM >in the executable</EM >, and a derived, <EM >implementation</EM > class <EM >in the module</EM >. Generally the interface class is abstract (a class is abstract if it has pure virtual functions).</P ><P >As dynamic loading of classes is generally used for plug-ins — which must expose a clearly defined interface — we would have had to define an interface and derived implementation classes anyway.</P ><P >Next, while still in the module, we define two additional helper functions, known as <EM >class factory functions</EM >. One of these functions creates an instance of the class and returns a pointer to it. The other function takes a pointer to a class created by the factory and destroys it. These two functions are qualified as <TT CLASS="literal" >extern "C"</TT >.</P ><P >To use the class from the module, load the two factory functions using <TT CLASS="function" >dlsym</TT > just <A HREF="thesolution.html#loadingfunctions" >as we loaded the the hello function</A >; then, we can create and destroy as many instances as we wish.</P ><DIV CLASS="example" ><A NAME="AEN216" ></A ><P ><B >Example 2. Loading a Class</B ></P ><P >Here we use a generic <TT CLASS="classname" >polygon</TT > class as interface and the derived class <TT CLASS="classname" >triangle</TT > as implementation.</P ><P >main.cpp:</P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="programlisting" >#include "polygon.hpp" #include <iostream> #include <dlfcn.h> int main() { using std::cout; using std::cerr; // load the triangle library void* triangle = dlopen("./triangle.so", RTLD_LAZY); if (!triangle) { cerr << "Cannot load library: " << dlerror() << '\n'; return 1; } // reset errors dlerror(); // load the symbols create_t* create_triangle = (create_t*) dlsym(triangle, "create"); const char* dlsym_error = dlerror(); if (dlsym_error) { cerr << "Cannot load symbol create: " << dlsym_error << '\n'; return 1; } destroy_t* destroy_triangle = (destroy_t*) dlsym(triangle, "destroy"); dlsym_error = dlerror(); if (dlsym_error) { cerr << "Cannot load symbol destroy: " << dlsym_error << '\n'; return 1; } // create an instance of the class polygon* poly = create_triangle(); // use the class poly->set_side_length(7); cout << "The area is: " << poly->area() << '\n'; // destroy the class destroy_triangle(poly); // unload the triangle library dlclose(triangle); }</PRE ></FONT ></TD ></TR ></TABLE ><P >polygon.hpp:</P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="programlisting" >#ifndef POLYGON_HPP #define POLYGON_HPP class polygon { protected: double side_length_; public: polygon() : side_length_(0) {} virtual ~polygon() {} void set_side_length(double side_length) { side_length_ = side_length; } virtual double area() const = 0; }; // the types of the class factories typedef polygon* create_t(); typedef void destroy_t(polygon*); #endif</PRE ></FONT ></TD ></TR ></TABLE ><P >triangle.cpp:</P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="programlisting" >#include "polygon.hpp" #include <cmath> class triangle : public polygon { public: virtual double area() const { return side_length_ * side_length_ * sqrt(3) / 2; } }; // the class factories extern "C" polygon* create() { return new triangle; } extern "C" void destroy(polygon* p) { delete p; } </PRE ></FONT ></TD ></TR ></TABLE ></DIV ><P >There are a few things to note when loading classes:</P ><P ></P ><UL ><LI ><P >You must provide <EM >both</EM > a creation and a destruction function; you must <EM >not</EM > destroy the instances using <TT CLASS="literal" >delete</TT > from inside the executable, but always pass it back to the module. This is due to the fact that in C++ the operators <TT CLASS="literal" >new</TT > and <TT CLASS="literal" >delete</TT > may be overloaded; this would cause a non-matching <TT CLASS="literal" >new</TT > and <TT CLASS="literal" >delete</TT > to be called, which could cause anything from nothing to memory leaks and segmentation faults. The same is true if different standard libraries are used to link the module and the executable.</P ></LI ><LI ><P >The destructor of the interface class should be virtual in any case. There <EM >might</EM > be very rare cases where that would not be necessary, but it is not worth the risk, because the additional overhead can generally be ignored.</P ><P >If your base class needs no destructor, define an empty (and <TT CLASS="literal" >virtual</TT >) one anyway; otherwise you <EM >will have problems</EM > sooner or later; I can guarantee you that. You can read more about this problem in the comp.lang.c++ FAQ at <A HREF="http://www.parashift.com/c++-faq-lite/" TARGET="_top" >http://www.parashift.com/c++-faq-lite/</A >, in section 20.</P ></LI ></UL ></DIV ></DIV ><DIV CLASS="NAVFOOTER" ><HR ALIGN="LEFT" WIDTH="100%"><TABLE SUMMARY="Footer navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" ><A HREF="theproblem.html" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="index.html" ACCESSKEY="H" >Home</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" ><A HREF="source.html" ACCESSKEY="N" >Next</A ></TD ></TR ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" >The Problem</TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" > </TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" >Source Code</TD ></TR ></TABLE ></DIV ></BODY ></HTML >