mirror of
https://github.com/boostorg/fiber.git
synced 2026-02-20 14:42:21 +00:00
189 lines
7.1 KiB
Plaintext
189 lines
7.1 KiB
Plaintext
[/ Boost.Extension - second tutorial ]
|
|
[/ Copyright 2008 Jeremy Pack ]
|
|
[/ Distributed under the Boost Software License, Version 1.0. (See]
|
|
[/ accompanying file LICENSE_1_0.txt or copy at ]
|
|
[/ http://www.boost.org/LICENSE_1_0.txt) ]
|
|
[/ See http://www.boost.org/ for latest version. ]
|
|
|
|
[section:tutorial03 Tutorial 3 - Multiple and Implementation Inheritance]
|
|
|
|
This tutorial shows more advanced class loading. The example described here is
|
|
contrived, and such a convoluted design is not used as an example of good
|
|
object-oriented program, but as a way to illustrate some of the possibilities
|
|
with this library.
|
|
|
|
Most complications with this type of factory usage only occur on Windows, or with
|
|
less popular compiler options. Refer to
|
|
[link boost_extension.appendices.appendix_a Appendix A].
|
|
|
|
Let's design a class hierarchy based on the following:
|
|
|
|
|
|
* There is a vehicle class
|
|
* There is a computer class
|
|
* A car is a vehicle
|
|
* A boat is a vehicle
|
|
* A plane is a vehicle
|
|
* A flying_car is a plane and a car
|
|
* A car_of_the_future is a flying_car, a boat, and a computer.
|
|
|
|
|
|
In addition, we are not going to have any of these classes be interfaces. They
|
|
will each have an implementation in a .cpp file. This will require multiple
|
|
inheritance, as well as virtual inheritance (because otherwise a
|
|
car_of_the_future would consist of three separate vehicle base classes!).
|
|
|
|
|
|
In addition, each class will be compiled into a separate shared library. This
|
|
is not necessary, certainly, but will serve to illustrate some of the more
|
|
advanced capabilities of the library, as well as some of the techniques
|
|
necessary in this situation.
|
|
|
|
|
|
To begin with, let's look at the Jamfile:
|
|
|
|
|
|
``
|
|
import type : change-generated-target-suffix ;
|
|
import type : change-generated-target-prefix ;
|
|
type.change-generated-target-suffix SHARED_LIB : : extension ;
|
|
type.change-generated-target-prefix SHARED_LIB : : lib ;
|
|
``
|
|
|
|
As usual, first we must rename the generated libraries (this is required for
|
|
cross-platform use - but the prefix and suffix are arbitrary).
|
|
|
|
Next, some special options are needed for certain compilers, to make sure
|
|
that the shared libraries are found correctly. This is only needed for this
|
|
example because we have shared libraries that are linked by the linker after
|
|
compilation to other shared libraries, rather than loaded by the shared_library
|
|
class at runtime. Library paths and includes need to be set as follows:
|
|
|
|
``
|
|
local BOOST_ROOT = [ os.environ BOOST_ROOT ] ;
|
|
project
|
|
: requirements
|
|
<include>../../../
|
|
<include>$(BOOST_ROOT)
|
|
<toolset>gcc:<find-shared-library>dl
|
|
<toolset>gcc:<linkflags>"-Wl,-rpath,'$ORIGIN'"
|
|
<toolset>darwin:<define>DYLD_LIBRARY_PATH=./
|
|
:
|
|
;
|
|
|
|
``
|
|
|
|
The rules for building the first two libraries are the same
|
|
as those from earlier tutorials.
|
|
|
|
``
|
|
lib Vehicle : multiple_inheritance/vehicle.cpp : <link>shared ;
|
|
lib Car : multiple_inheritance/car.cpp Vehicle : <link>shared ;
|
|
``
|
|
|
|
|
|
Notice here that the Car library is linked to the Vehicle library - this is
|
|
necessary because the Car class needs the implementation of the Vehicle class.
|
|
This is not specific to the Boost.Extension library, but just a standard
|
|
requirement when inheriting from shared library classes. The same will be done
|
|
with the other shared libraries.
|
|
|
|
|
|
``
|
|
lib Plane : multiple_inheritance/plane.cpp Vehicle : <link>shared ;
|
|
lib Boat : multiple_inheritance/boat.cpp Vehicle : <link>shared ;
|
|
lib Computer : multiple_inheritance/computer.cpp : <link>shared ;
|
|
lib FlyingCar : multiple_inheritance/flying_car.cpp Plane Car Vehicle
|
|
: <link>shared ;
|
|
lib CarOfTheFuture :
|
|
multiple_inheritance/car_of_the_future.cpp
|
|
Plane Car Vehicle
|
|
FlyingCar Computer Boat
|
|
:
|
|
<link>shared
|
|
;
|
|
|
|
install ../bin :
|
|
HelloWorld HelloWorldLib Vehicle Boat FlyingCar
|
|
CarOfTheFuture MultipleInheritance
|
|
:
|
|
;
|
|
``
|
|
|
|
|
|
Refer to the examples/multiple_inheritance folder for the source code of these
|
|
classes. Only the most complex will be described here - the rest are similar.
|
|
|
|
|
|
On the Windows platform, there are special declarations that are required when
|
|
a dll must use a class that is defined in another dll. For interface only
|
|
classes this is unnecessary, and is not needed on other platforms. The macros
|
|
BOOST_EXTENSION_IMPORT_DECL and BOOST_EXTENSION_EXPORT_DECL can be used
|
|
to insert the proper declaration. This is detailed in
|
|
[link boost_extension.appendices.appendix_a Appendix A].
|
|
|
|
The macros here are defined in such a way that in the `car_of_the_future`
|
|
class, the classes it depends on from other shared libraries are
|
|
declared as imports. The BOOST_EXTENSION_CAR_OF_THE_FUTURE_DECL must be
|
|
defined by any source file using this class - as `BOOST_EXTENSION_IMPORT_DECL`
|
|
by the shared library containing the `car_of_the_future`, and as
|
|
`BOOST_EXTENSION_EXPORT_DECL` by any shared library or executable linking
|
|
directly to that shared library.
|
|
|
|
``
|
|
#define BOOST_EXTENSION_FLYING_CAR_DECL BOOST_EXTENSION_IMPORT_DECL
|
|
#define BOOST_EXTENSION_BOAT_DECL BOOST_EXTENSION_IMPORT_DECL
|
|
#define BOOST_EXTENSION_COMPUTER_DECL BOOST_EXTENSION_IMPORT_DECL
|
|
#include "flying_car.hpp"
|
|
#include "boat.hpp"
|
|
#include "computer.hpp"
|
|
#include <iostream>
|
|
#include <typeinfo>
|
|
class BOOST_EXTENSION_CAR_OF_THE_FUTURE_DECL
|
|
car_of_the_future : public flying_car, public boat, public computer
|
|
{
|
|
public:
|
|
car_of_the_future(void){std::cout << "\nCreated a Car of the Future";}
|
|
~car_of_the_future(void){std::cout << "\nDestroyed a Car of the Future";}
|
|
virtual std::string list_capabilities(void);
|
|
};
|
|
``
|
|
|
|
In the implementation file for the `car_of_the_future`, it is exported
|
|
as an implementation of each of its base classes.
|
|
|
|
``
|
|
std::string car_of_the_future::list_capabilities() {
|
|
return boat::list_capabilities() + flying_car::list_capabilities() +
|
|
computer::list_capabilities() + "\nCosts an arm and a leg";
|
|
}
|
|
|
|
using boost::extensions::factory;
|
|
|
|
BOOST_EXTENSION_TYPE_MAP_FUNCTION {
|
|
types.get<std::map<std::string, factory<vehicle> > >()
|
|
["A car of the future exported as a vehicle"].set<car_of_the_future>();
|
|
types.get<std::map<std::string, factory<car> > >()
|
|
["A car of the future exported as a car"].set<car_of_the_future>();
|
|
types.get<std::map<std::string, factory<plane> > >()
|
|
["A car of the future exported as a plane"].set<car_of_the_future>();
|
|
types.get<std::map<std::string, factory<flying_car> > >()
|
|
["A car of the future exported as a flying car"].set<car_of_the_future>();
|
|
types.get<std::map<std::string, factory<boat> > >()
|
|
["A car of the future exported as a boat"].set<car_of_the_future>();
|
|
types.get<std::map<std::string, factory<computer> > >()
|
|
["A car of the future exported as a computer"].set<car_of_the_future>();
|
|
types.get<std::map<std::string, factory<car_of_the_future> > >()
|
|
["A car of the future exported as a car of the future"].set<car_of_the_future>();
|
|
}
|
|
``
|
|
|
|
The main executable is relatively straightforward, but does introduce a new
|
|
function: `load_single_library`, which takes a _type_map_ and the location
|
|
of the shared library, and loads the library and calls the function declared
|
|
as `BOOST_EXTENSION_TYPE_MAP_FUNCTION`.
|
|
|
|
Now, place all of the compiled libraries and the main executable in a directory together,
|
|
and run the executable.
|
|
|
|
[endsect] |