//==================================================================================================
// S t a n d a r d                                                                        Interface
// D y n a m i c L o a d i n g
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. This library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
// the GNU Library General Public License for more details (http://www.gnu.org).

/*DESCRIPTION*/
/* This module provides elements to load a dynamic library. */

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "standard/dynamic_loading.hpp"

// Guardian //--------------------------------------------------------------------------------------
#ifndef guStandardDynamicLoading
#define guStandardDynamicLoading

// Headers //---------------------------------------------------------------------------------------
#include <bpp/standard/environment.hpp> /*INCLUDE*/
#include <bpp/standard/error.hpp> /*INCLUDE*/
#include DYNAMIC_LOADING_HEADER /*INCLUDE*/

namespace bpp {

// Importation/Exportation //-----------------------------------------------------------------------
#ifdef STANDARD_DLL
 #define dll_export DLL_EXPORT
#else
 #define dll_export DLL_IMPORT
#endif

// Namespaces //------------------------------------------------------------------------------------
#define public_area  standardDynamicLoading
#define private_area standardDynamicLoading_private

namespace public_area  { /*NAMESPACE*/ using namespace standardError; }
namespace private_area { using namespace public_area; }

extern_module_name;

// Initialization //--------------------------------------------------------------------------------
#define iniStandardDynamicLoading
has_initializer;

// Macrocommands //---------------------------------------------------------------------------------

// Types & Classes //-------------------------------------------------------------------------------
namespace public_area {
 //------------------------------------------------------------------------------------------Classes
 class clDynamicLibrary;
 //-----------------------------------------------------------------------------------Variable Types
 /*TYPE*/ /* Pointer to a dynamic library. */
 typedef DYNAMIC_LIBRARY_TYPE tyDynamicLibrary;
 //-----------------------------------------------------------------------------------Constant Types
 typedef const tyDynamicLibrary tcDynamicLibrary;
 typedef const clDynamicLibrary ctDynamicLibrary;
}

namespace private_area {}

// Functions Interface //---------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// Errors //----------------------------------------------------------------------------------------
namespace public_area {
 /*ERROR*/ extern_error erGetDynamicSymbol; /* Can not get the dynamic symbol. */
 /*ERROR*/ extern_error erLoadDynamicLibrary; /* Can not load the dynamic library. */
}

// Constants & Variables //-------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// D y n a m i c L i b r a r y  Interface //--------------------------------------------------------
namespace public_area {
 /*CLASS clDynamicLibrary */ /* Represents a dynamic library. */
 class clDynamicLibrary {
  //-----------------------------------------------------------------------------------------Private
  private_property clDynamicLibrary & operator = (ctDynamicLibrary &);
  private_property constructor clDynamicLibrary(ctDynamicLibrary &);
  //------------------------------------------------------------------------------------------Public
  /*ATTRIBUTE clDynamicLibrary */ /* Pointer to the dynamic library. */
  read_only_attribute(tyDynamicLibrary,atPointer,pointer);

  public_property constructor clDynamicLibrary(void);
  public_property constructor clDynamicLibrary(tcString);
  public_property destructor  clDynamicLibrary();

  public_property void       load(tcString);
  public_property tyFunction symbol(tcString) const;
 };
}

// Functions Inline //------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// D y n a m i c L i b r a r y  Inline //-----------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clDynamicLibrary */ /* Builds a dynamic library object. No library is loaded */
 inline clDynamicLibrary::clDynamicLibrary(void) : atPointer(nil) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clDynamicLibrary */ /* Builds a dynamic library object and loads the library. */
 inline clDynamicLibrary::clDynamicLibrary(tcString agName) : atPointer(nil) {
  atPointer=(DYNAMIC_LIBRARY_TYPE)LOAD_DYNAMIC_LIBRARY_COMMAND(agName);
  if (atPointer==nil) send_inline_error(erLoadDynamicLibrary,"dynamicLibrary::constructor");
 }
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clDynamicLibrary */ /* Unloads the dynamic library. */
 inline clDynamicLibrary::~clDynamicLibrary(void) {
  if (atPointer!=nil) UNLOAD_DYNAMIC_LIBRARY_COMMAND(atPointer);
 }
 //---------------------------------------------------------------------------------------------Load
 /*METHOD clDynamicLibrary */ /* Loads a dynamic library. */
 inline void clDynamicLibrary::load(tcString agName) {
  if (atPointer!=nil) send_inline_error(erLoadDynamicLibrary,"dynamicLibrary::load");
  atPointer=(DYNAMIC_LIBRARY_TYPE)LOAD_DYNAMIC_LIBRARY_COMMAND(agName);
  if (atPointer==nil) send_inline_error(erLoadDynamicLibrary,"dynamicLibrary::load");
 }
 //-------------------------------------------------------------------------------------------Symbol
 /*METHOD clDynamicLibrary */ /* Returns a pointer to a given symbol in the library. */
 inline tyFunction clDynamicLibrary::symbol(tcString agName) const {
  tyUniversalPointer lcPointer;

  lcPointer.toFunction=nil;

  if (atPointer==nil) send_inline_error(erGetDynamicSymbol,"dynamicLibrary::symbol");
  else {
   GET_DYNAMIC_SYMBOL_COMMAND(lcPointer,atPointer,agName);
   if (lcPointer.toFunction==nil) send_inline_error(erGetDynamicSymbol,"dynamicLibrary::symbol");
  }

  return (lcPointer.toFunction);
 }
}

// End //-------------------------------------------------------------------------------------------
}
#undef dll_export
#undef public_area
#undef private_area
#endif
 
//==================================================================================================
// S t a n d a r d                                                                   Implementation
// D y n a m i c L o a d i n g
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. This library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
// the GNU Library General Public License for more details (http://www.gnu.org).

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "standard/dynamic_loading.cpp"

// DLL Belonging //---------------------------------------------------------------------------------
#define STANDARD_DLL

// Headers //---------------------------------------------------------------------------------------
#include <bpp/standard/dynamic_loading.hpp> /*INTERFACE*/

namespace bpp {

// Namespaces //------------------------------------------------------------------------------------
#define public_area  standardDynamicLoading
#define private_area standardDynamicLoading_private
#define dll_export   DLL_EXPORT

namespace public_area  {}
namespace private_area {}

static_module_name("Standard/Dynamic_loading");

// Initialization //--------------------------------------------------------------------------------
#undef iniStandardDynamicLoading
static_constant(private_area::clInitializer,goInitializer);

// Errors //----------------------------------------------------------------------------------------
namespace public_area {
 static_error erGetDynamicSymbol;
 static_error erLoadDynamicLibrary;
}

// Constants & Variables //-------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// Static Members //--------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// Functions Implementation //----------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// X X X  Implementation //-------------------------------------------------------------------------
namespace {}

// I n i t i a l i z e r  Implementation //---------------------------------------------------------
namespace private_area {
 //--------------------------------------------------------------------------------------------Start
 property void clInitializer::start(void) {
  if (atCounter++ == 0) {
   try {
    #include <bpp/modules.hpp> /*NEED*/
    registerStop(this);
    environment::informInitialization(goModuleName);

    erGetDynamicSymbol.create("Can't get the dynamic symbol.");
    erLoadDynamicLibrary.create("Can't load the dynamic library.");
   }

   initializer_catch;
  }
 }
 //---------------------------------------------------------------------------------------------Stop
 property void clInitializer::stop(void) { environment::informTermination(goModuleName); }
}

// End //-------------------------------------------------------------------------------------------
}