And the USA has again put a rover on Mars

We did it again!  Curiosity is on Mars! Here’s to all the men and women over at NASA Jet Propulsion Laboratory and any others who worked on the project.  Now the real work begins lol

http://mars.jpl.nasa.gov/msl-raw-images/proj/msl/redops/ods/surface/sol/00000/opgs/edr/fcam/FRA_397502305EDR_T0010000AUT_04096M_.JPG

– Teknoman117

Advertisements

C++ Plugins with Boost::Function on Linux

Over the past few weeks, one of the concepts that I’ve been experimenting with is plugin architecture.  The idea of having a core application which can be extended by shared objects without recompiling the core program.  Or, possibly, a way of defining more services in an application based around plugins.  What I’ve done so far hasn’t been much, but, I haven’t spent much time working on it.  When I started out on researching it, one of the things I wanted was to be able to was define a C++ object in a plugin and be able to instantiate that object in the main program.  So, this is what I have come up with.  There are three parts of this solution: the plugin class definition in plugin.hpp, the plugin in someplugin.cpp, and the loader code in loader.cpp.  I’ve also included a CMakeLists.txt file to compile it with cmake.

plugin.hpp

#ifndef _PLUGIN_HPP_
#define _PLUGIN_HPP_

#include <string>

namespace plugins
{
  class Plugin 
  {  
  public:
    virtual std::string toString() = 0;
  };
}

#endif

awesomeplugin.cpp

#include "plugin.hpp"

namespace plugins
{
  class AwesomePlugin : public Plugin
  {  
  public:
    // A function to do something, so we can demonstrate the plugin
    std::string toString()
    {
      return std::string("Coming from awesome plugin");
    }
  };
}

extern "C" 
{
  // Function to return an instance of a new AwesomePlugin object
  plugins::Plugin* construct()
  {
    return new plugins::AwesomePlugin();
  }
}

loader.cpp

#include <iostream>
#include <vector>
#include <dlfcn.h>
#include <boost/function.hpp>

#include "plugin.hpp"

typedef std::vector<std::string>             StringVector;
typedef boost::function<plugins::Plugin* ()> pluginConstructor;

int main (int argc, char** argv)
{
  // Assemble the names of plugins to load
  StringVector plugins;
  for(int i = 1; i < argc; i++)
  {
    plugins.push_back(argv[i]);
  }

  // Iterate through all the plugins and call construct and use an instance
  for(StringVector::iterator it = plugins.begin(); it != plugins.end(); it++)
  {
    // Alert that we are attempting to load a plugin
    std::cout << "Loading plugin \"" << *it << "\"" << it->c_str() << std::endl;

    // Load the plugin's .so file
    void *handle = NULL;
    if(!(handle = dlopen(it->c_str(), RTLD_LAZY)))
    {
      std::cerr << "Plugin: " << dlerror() << std::endl;
      continue;
    }
    dlerror();

    // Get the pluginConstructor function
    pluginConstructor construct = (plugins::Plugin* (*)(void)) dlsym(handle, "construct");
    char *error = NULL;
    if((error = dlerror()))
    {
      std::cerr << "Plugin: " << dlerror() << std::endl;
      dlclose(handle);
      continue;
    }

    // Construct a plugin
    plugins::Plugin *plugin = construct();
    std::cout << "[Plugin " << *it << "] " << plugin->toString() << std::endl;
    delete plugin;

    // Close the plugin
    dlclose(handle);
  }

  return 0;
}

CMakeLists.txt

# Project Stuff
cmake_minimum_required (VERSION 2.6)
project (PluginDemo)

# Default Options
add_definitions("-std=c++0x")

# Find Boost
find_package(Boost REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})

# Pull in the project includes
include_directories(${PROJECT_SOURCE_DIR}/include)
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
set(LIBS ${LIBS} pthread boost_thread rt)

# Build the plugin experiment
add_executable(pluginloader src/loader.cpp)
target_link_libraries(pluginloader ${LIBS} dl)
add_library(awesomeplugin SHARED src/awesomeplugin.cpp)

Basically create a directory with the folders bin, lib, and src. Put loader.cpp, awesomeplugin.cpp, and plugin.hpp in src, and CMakeLists.txt in the directory. Open a terminal and run “cmake . && make”. Run the pluginloader program and pass it the path to the plugin’s .so in the lib folder. Here is the output from my computer.

nathaniel@XtremePC:~/Programming/Experimentation> cmake .
— The C compiler identification is GNU
— The CXX compiler identification is GNU
— Check for working C compiler: /usr/bin/gcc
— Check for working C compiler: /usr/bin/gcc — works
— Detecting C compiler ABI info
— Detecting C compiler ABI info – done
— Check for working CXX compiler: /usr/bin/c++
— Check for working CXX compiler: /usr/bin/c++ — works
— Detecting CXX compiler ABI info
— Detecting CXX compiler ABI info – done
— Boost version: 1.46.1
— Configuring done
— Generating done
— Build files have been written to: /home/nathaniel/Programming/Experimentation
nathaniel@XtremePC:~/Programming/Experimentation> make
Scanning dependencies of target awesomeplugin
[ 50%] Building CXX object CMakeFiles/awesomeplugin.dir/Plugins/awesomeplugin.cpp.o
Linking CXX shared library lib/libawesomeplugin.so
[ 50%] Built target awesomeplugin
Scanning dependencies of target pluginloader
[100%] Building CXX object CMakeFiles/pluginloader.dir/Plugins/loader.cpp.o
Linking CXX executable bin/pluginloader
[100%] Built target pluginloader
nathaniel@XtremePC:~/Programming/Experimentation> bin/pluginloader lib/libawesomeplugin.so
Loading plugin “lib/libawesomeplugin.so”
[Plugin lib/libawesomeplugin.so] Coming from awesome plugin
nathaniel@XtremePC:~/Programming/Experimentation>

– Teknoman117