file Backends/backend_macros.hpp

[No description available] More…

Defines

Name
BE_FUNCTION_5(NAME, TYPE, ARGSLIST, SYMBOLNAMES, CAPABILITY)
BE_FUNCTION_6(NAME, TYPE, ARGSLIST, SYMBOLNAMES, CAPABILITY, MODELS)
BE_FUNCTION_7(NAME, TYPE, ARGSLIST, SYMBOLNAMES, CAPABILITY, MODELS, REF)
BE_FUNCTION(…)
BE_FUNCTION_I(NAME, TYPE, ARGLIST, SYMBOLNAMES, CAPABILITY, MODELS, REF)
BE_FUNCTION_I_AUX(NAME, TYPE, ARGLIST, SYMBOLNAMES, CAPABILITY, MODELS)
BE_FUNCTION_I_OTHER(NAME, TYPE, ARGLIST, SYMBOLNAMES, CAPABILITY, MODELS)
Backend function macro for other backends (C/C++/Fortran)
BE_FUNCTION_I_MAIN(NAME, TYPE, ARGLIST, SYMBOLNAMES, CAPABILITY, MODELS, REF)
Main actual backend function macro.
BE_FUNCTION_I_SUPP(NAME)
Supplemenentary backend function macro.
BE_CONV_FUNCTION_FULL(NAME, TYPE, ARGSLIST, CAPABILITY, MODELS, REF)
BE_CONV_FUNCTION_MAIN(NAME, TYPE, ARGSLIST, CAPABILITY, MODELS, REF)
BE_CONV_FUNCTION_SUPP(NAME)
ARG_NAME(R, DATA, INDEX, ELEM)
Macros to add names to an argument list.
FUNCTION_ARGS_SEQ(ARGLIST)
FUNCTION_ARGS(ARGLIST)
ARG_NAME_ONLY(R, DATA, INDEX, ELEM)
Macros to get only the names corresponding to an argument list.
FUNCTION_ARG_NAMES_SEQ(ARGLIST)
FUNCTION_ARG_NAMES(ARGLIST)
MODULE
Declare the backend initialisation module BackendIniBit.
BE_INI_DEPENDENCY(DEP, TYPE)
Dependency macro for point-level backend initialisation functions (in BackendIniBit)
BE_INI_CONDITIONAL_DEPENDENCY(DEP, TYPE, …)
Model-conditional dependency macro for point-level backend initialisation functions (in BackendIniBit)
BE_ALLOW_MODEL(MODEL)
Macro for assigning a single allowed model to an entire backend.
SET_ALLOWED_MODELS(NAME, MODELS)
Set all the allowed models for a given backend functor.
MAKE_INUSE_POINTER(NAME)
Make the inUse pipe for a given backend functor.
LOAD_LIBRARY
Macro containing initialization code.
REGISTER_BACKEND(BE, VER, SAFEVER, REF)
Register this backend with the Core if not running in standalone mode.
LOAD_ALL_FACTORIES
Load factory functions for classes provided by this backend.
LOAD_FACTORIES_FOR_TYPE(r, data, elem)
Load all factory functions for a given type.
LOAD_NTH_FACTORY_FOR_TYPE(r, data, i, elem)
Redirector from within BOOST_PP_SEQ_FOR_EACH_I to LOAD_SINGLE_FACTORY.
LOAD_SINGLE_FACTORY(BARENAME, NAME, ARGS, SYMBOLNAMES, ABSTRACT, PTRNAME)
Load a single factory function from a backend.
BE_VARIABLE_I(NAME, TYPE, SYMBOLNAMES, CAPABILITY, MODELS, REF)
BE_VARIABLE_I_AUX(NAME, TYPE, SYMBOLNAMES, CAPABILITY, MODELS)
BE_VARIABLE_I_OTHER(NAME, TYPE, SYMBOLNAMES, CAPABILITY, MODELS)
Backend variable macro for regular backends (C/C++/Fortran)
BE_VARIABLE_I_MAIN(NAME, TYPE, SYMBOLNAMES, CAPABILITY, MODELS, REF)
Main actual backend variable macro.
BE_VARIABLE_I_SUPP(NAME)
Supplementary backend variable macro.

Detailed Description

Author:

Date:

  • 2013 Mar, Apr, Nov
  • 2013 June
  • 2013 July
  • 2014 Jan, Mar, May
  • 2015 Feb
  • 2017 Dec
  • 2014 Jan, Mar
  • 2015 Jan, Feb
  • 2016 Sep
  • 2021 Sep

General macros for loading a shared library and constructing pointers to the variables and functions within the library.


Authors (add name and date if you modify):


Macros Documentation

define BE_FUNCTION_5

#define BE_FUNCTION_5(
    NAME,
    TYPE,
    ARGSLIST,
    SYMBOLNAMES,
    CAPABILITY
)
BE_FUNCTION_I(NAME, TYPE, ARGSLIST, SYMBOLNAMES, CAPABILITY, (), "")

define BE_FUNCTION_6

#define BE_FUNCTION_6(
    NAME,
    TYPE,
    ARGSLIST,
    SYMBOLNAMES,
    CAPABILITY,
    MODELS
)
BE_FUNCTION_I(NAME, TYPE, ARGSLIST, SYMBOLNAMES, CAPABILITY, MODELS, "")

define BE_FUNCTION_7

#define BE_FUNCTION_7(
    NAME,
    TYPE,
    ARGSLIST,
    SYMBOLNAMES,
    CAPABILITY,
    MODELS,
    REF
)
BE_FUNCTION_I(NAME, TYPE, ARGSLIST, SYMBOLNAMES, CAPABILITY, MODELS, REF)

define BE_FUNCTION

#define BE_FUNCTION(
    ...
)
VARARG(BE_FUNCTION, __VA_ARGS__)

define BE_FUNCTION_I

#define BE_FUNCTION_I(
    NAME,
    TYPE,
    ARGLIST,
    SYMBOLNAMES,
    CAPABILITY,
    MODELS,
    REF
)
          BE_FUNCTION_I_AUX(NAME, TYPE, ARGLIST, SYMBOLNAMES, CAPABILITY, MODELS)               \
          BE_FUNCTION_I_MAIN(NAME, TYPE, ARGLIST, SYMBOLNAMES, CAPABILITY, MODELS, REF)         \
          BE_FUNCTION_I_SUPP(NAME)

define BE_FUNCTION_I_AUX

#define BE_FUNCTION_I_AUX(
    NAME,
    TYPE,
    ARGLIST,
    SYMBOLNAMES,
    CAPABILITY,
    MODELS
)
        IF_ELSEIF(USING_MATHEMATICA, BE_FUNCTION_I_MATH,                                        \
                  USING_PYTHON, BE_FUNCTION_I_PY,                                               \
                  BE_FUNCTION_I_OTHER)(NAME, TYPE, ARGLIST, SYMBOLNAMES, CAPABILITY, MODELS)

define BE_FUNCTION_I_OTHER

#define BE_FUNCTION_I_OTHER(
    NAME,
    TYPE,
    ARGLIST,
    SYMBOLNAMES,
    CAPABILITY,
    MODELS
)
namespace Gambit                                                                                \
{                                                                                               \
  namespace Backends                                                                            \
  {                                                                                             \
    namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                                                 \
    {                                                                                           \
      /* Define a type NAME_type to be a suitable function pointer. */                          \
      typedef TYPE (*NAME##_type) CONVERT_VARIADIC_ARG(ARGLIST);                                \
                                                                                                \
      extern const NAME##_type NAME = load_backend_symbol<NAME##_type>(initVector<str>(         \
      STRIP_PARENS(SYMBOLNAMES)), STRINGIFY(BACKENDNAME), STRINGIFY(VERSION));                  \
                                                                                                \
    }                                                                                           \
  }                                                                                             \
}

Backend function macro for other backends (C/C++/Fortran)

define BE_FUNCTION_I_MAIN

#define BE_FUNCTION_I_MAIN(
    NAME,
    TYPE,
    ARGLIST,
    SYMBOLNAMES,
    CAPABILITY,
    MODELS,
    REF
)

Main actual backend function macro.

define BE_FUNCTION_I_SUPP

#define BE_FUNCTION_I_SUPP(
    NAME
)
namespace Gambit                                                                                \
{                                                                                               \
  namespace Backends                                                                            \
  {                                                                                             \
    namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                                                 \
    {                                                                                           \
      int CAT(fptr_supp_,NAME) = register_backend_functor(Functown::NAME);                      \
    }                                                                                           \
  }                                                                                             \
}                                                                                               \

Supplemenentary backend function macro.

define BE_CONV_FUNCTION_FULL

#define BE_CONV_FUNCTION_FULL(
    NAME,
    TYPE,
    ARGSLIST,
    CAPABILITY,
    MODELS,
    REF
)
          BE_CONV_FUNCTION_MAIN(NAME, TYPE, ARGSLIST, CAPABILITY, MODELS, REF)                  \
          BE_CONV_FUNCTION_SUPP(NAME)

define BE_CONV_FUNCTION_MAIN

#define BE_CONV_FUNCTION_MAIN(
    NAME,
    TYPE,
    ARGSLIST,
    CAPABILITY,
    MODELS,
    REF
)

define BE_CONV_FUNCTION_SUPP

#define BE_CONV_FUNCTION_SUPP(
    NAME
)
namespace Gambit                                                                                \
{                                                                                               \
  namespace Backends                                                                            \
  {                                                                                             \
    namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                                                 \
    {                                                                                           \
      int CAT(cfptr_supp_,NAME) = register_backend_functor(Functown::NAME);                     \
    }                                                                                           \
  }                                                                                             \
}                                                                                               \

define ARG_NAME

#define ARG_NAME(
    R,
    DATA,
    INDEX,
    ELEM
)
(ELEM arg##INDEX)

Macros to add names to an argument list.

define FUNCTION_ARGS_SEQ

#define FUNCTION_ARGS_SEQ(
    ARGLIST
)
        BOOST_PP_IF(ISEMPTY(ARGLIST), (),                            \
        BOOST_PP_SEQ_FOR_EACH_I(ARG_NAME, , BOOST_PP_TUPLE_TO_SEQ(ARGLIST)))

define FUNCTION_ARGS

#define FUNCTION_ARGS(
    ARGLIST
)
BOOST_PP_SEQ_TO_TUPLE(FUNCTION_ARGS_SEQ(ARGLIST))

define ARG_NAME_ONLY

#define ARG_NAME_ONLY(
    R,
    DATA,
    INDEX,
    ELEM
)
(std::forward<ELEM>(arg##INDEX))

Macros to get only the names corresponding to an argument list.

define FUNCTION_ARG_NAMES_SEQ

#define FUNCTION_ARG_NAMES_SEQ(
    ARGLIST
)
        BOOST_PP_IF(ISEMPTY(ARGLIST), (),                       \
        BOOST_PP_SEQ_FOR_EACH_I(ARG_NAME_ONLY, , BOOST_PP_TUPLE_TO_SEQ(ARGLIST)))

define FUNCTION_ARG_NAMES

#define FUNCTION_ARG_NAMES(
    ARGLIST
)
BOOST_PP_SEQ_TO_TUPLE(FUNCTION_ARG_NAMES_SEQ(ARGLIST))

define MODULE

#define MODULE BackendIniBit

Declare the backend initialisation module BackendIniBit.

define BE_INI_DEPENDENCY

#define BE_INI_DEPENDENCY(
    DEP,
    TYPE
)
CORE_DEPENDENCY(DEP, TYPE, BackendIniBit, CAT_5(BACKENDNAME,_,SAFE_VERSION,_,init), NOT_MODEL)

Dependency macro for point-level backend initialisation functions (in BackendIniBit)

define BE_INI_CONDITIONAL_DEPENDENCY

#define BE_INI_CONDITIONAL_DEPENDENCY(
    DEP,
    TYPE,
    ...
)
CORE_START_CONDITIONAL_DEPENDENCY(BackendIniBit, CAT_5(BACKENDNAME,_,SAFE_VERSION,_,init), CAT_5(BACKENDNAME,_,SAFE_VERSION,_,init), DEP, TYPE, NOT_MODEL) \
  ACTIVATE_DEP_MODEL(BackendIniBit, CAT_5(BACKENDNAME,_,SAFE_VERSION,_,init), CAT_5(BACKENDNAME,_,SAFE_VERSION,_,init), DEP, NOT_MODEL, #__VA_ARGS__)

Model-conditional dependency macro for point-level backend initialisation functions (in BackendIniBit)

define BE_ALLOW_MODEL

#define BE_ALLOW_MODEL(
    MODEL
)
BE_NAMESPACE                                                                \
{                                                                           \
  namespace                                                                 \
  {                                                                         \
    const int UNUSED_OKCAT(MODEL,_OK) =                                    \
     vectorstr_push_back(allowed_models,STRINGIFY(MODEL));                  \
  }                                                                         \
}                                                                           \
END_BE_NAMESPACE                                                            \
CORE_ALLOWED_MODEL(BackendIniBit,CAT_4(BACKENDNAME,_,SAFE_VERSION,_init),   \
 MODEL, NOT_MODEL)                                                          \

Macro for assigning a single allowed model to an entire backend.

define SET_ALLOWED_MODELS

#define SET_ALLOWED_MODELS(
    NAME,
    MODELS
)
int CAT(allowed_models_set_,NAME) =                                         \
 set_allowed_models(Functown::NAME, allowed_models, STRINGIFY(MODELS));

Set all the allowed models for a given backend functor.

define MAKE_INUSE_POINTER

#define MAKE_INUSE_POINTER(
    NAME
)
  namespace BackendIniBit                                                   \
  {                                                                         \
    namespace Pipes                                                         \
    {                                                                       \
      namespace CAT_4(BACKENDNAME,_,SAFE_VERSION,_init)                     \
      {                                                                     \
        namespace InUse                                                     \
        {                                                                   \
          safe_ptr<bool> NAME = Backends::CAT_3(BACKENDNAME,_,SAFE_VERSION) \
                                ::Functown::NAME.inUsePtr();                \
        }                                                                   \
      }                                                                     \
    }                                                                       \
  }                                                                         \

Make the inUse pipe for a given backend functor.

define LOAD_LIBRARY

#define LOAD_LIBRARY 

Macro containing initialization code.

define REGISTER_BACKEND

#define REGISTER_BACKEND(
    BE,
    VER,
    SAFEVER,
    REF
)
   int CAT_4(BE,_,SAFEVER,_rego) =                                          \
    register_backend(STRINGIFY(BE), STRINGIFY(VER), SAFE_STRINGIFY(REF));

Register this backend with the Core if not running in standalone mode.

define LOAD_ALL_FACTORIES

#define LOAD_ALL_FACTORIES  BOOST_PP_SEQ_FOR_EACH(LOAD_FACTORIES_FOR_TYPE, , CAT_4(BACKENDNAME,_,SAFE_VERSION,_all_data))

Load factory functions for classes provided by this backend.

define LOAD_FACTORIES_FOR_TYPE

#define LOAD_FACTORIES_FOR_TYPE(
    r,
    data,
    elem
)

Load all factory functions for a given type.

define LOAD_NTH_FACTORY_FOR_TYPE

#define LOAD_NTH_FACTORY_FOR_TYPE(
    r,
    data,
    i,
    elem
)
LOAD_SINGLE_FACTORY(data, CAT_3(data,factory,i), BOOST_PP_TUPLE_ELEM(2,1,elem),                \
 BOOST_PP_TUPLE_ELEM(2,0,elem), CAT(data,abstract), CAT(data,wrapper)::CAT(__factory,i) )       \

Redirector from within BOOST_PP_SEQ_FOR_EACH_I to LOAD_SINGLE_FACTORY.

define LOAD_SINGLE_FACTORY

#define LOAD_SINGLE_FACTORY(
    BARENAME,
    NAME,
    ARGS,
    SYMBOLNAMES,
    ABSTRACT,
    PTRNAME
)

Load a single factory function from a backend.

define BE_VARIABLE_I

#define BE_VARIABLE_I(
    NAME,
    TYPE,
    SYMBOLNAMES,
    CAPABILITY,
    MODELS,
    REF
)
          BE_VARIABLE_I_AUX(NAME, TYPE, SYMBOLNAMES, CAPABILITY, MODELS)            \
          BE_VARIABLE_I_MAIN(NAME, MATH_TYPE(TYPE), SYMBOLNAMES, CAPABILITY,        \
                             MODELS, REF)                                           \
          BE_VARIABLE_I_SUPP(NAME)

define BE_VARIABLE_I_AUX

#define BE_VARIABLE_I_AUX(
    NAME,
    TYPE,
    SYMBOLNAMES,
    CAPABILITY,
    MODELS
)
        IF_ELSEIF(USING_MATHEMATICA, BE_VARIABLE_I_MATH,                            \
                  USING_PYTHON, BE_VARIABLE_I_PY,                                   \
                  BE_VARIABLE_I_OTHER)(NAME, TYPE, SYMBOLNAMES, CAPABILITY, MODELS)

define BE_VARIABLE_I_OTHER

#define BE_VARIABLE_I_OTHER(
    NAME,
    TYPE,
    SYMBOLNAMES,
    CAPABILITY,
    MODELS
)
namespace Gambit                                                              \
{                                                                             \
  namespace Backends                                                          \
  {                                                                           \
    namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                               \
    {                                                                         \
                                                                              \
      /* Set the variable pointer and the getptr function. */                 \
      extern TYPE* const NAME =                                               \
       load_backend_symbol<TYPE*>(initVector<str>(STRIP_PARENS(SYMBOLNAMES)), \
       STRINGIFY(BACKENDNAME), STRINGIFY(VERSION));                           \
      TYPE* CAT(getptr,NAME)() { return NAME; }                               \
                                                                              \
    }                                                                         \
  }                                                                           \
}

Backend variable macro for regular backends (C/C++/Fortran)

define BE_VARIABLE_I_MAIN

#define BE_VARIABLE_I_MAIN(
    NAME,
    TYPE,
    SYMBOLNAMES,
    CAPABILITY,
    MODELS,
    REF
)

Main actual backend variable macro.

define BE_VARIABLE_I_SUPP

#define BE_VARIABLE_I_SUPP(
    NAME
)
namespace Gambit                                                              \
{                                                                             \
  namespace Backends                                                          \
  {                                                                           \
    namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                               \
    {                                                                         \
      int CAT(vptr_supp_,NAME) = register_backend_functor(Functown::NAME);    \
    }                                                                         \
  }                                                                           \
}                                                                             \

Supplementary backend variable macro.

Source code

//   GAMBIT: Global and Modular BSM Inference Tool
//   *********************************************
///  \file
///
///  General macros for loading a shared library
///  and constructing pointers to the variables and
///  functions within the library.
///
///  *********************************************
///
///  Authors (add name and date if you modify):
///
///  \author Anders Kvellestad
///          (anders.kvellestad@fys.uio.no)
///  \date 2013 Mar, Apr, Nov
///
///  \author Christoph Weniger
///          (c.weniger@uva.nl)
///  \date 2013 June
///
///  \author Pat Scott
///          (patscott@physics.mcgill.ca)
///  \date 2013 July
///  \date 2014 Jan, Mar, May
///  \date 2015 Feb
///  \date 2017 Dec
///
///  \author Lars A. Dal
///          (l.a.dal@fys.uio.no)
///  \date 2014 Jan, Mar
///  \date 2015 Jan, Feb
///
///  \author Tomas Gonzalo
///          (t.e.gonzalo@fys.uio.no)
///  \date 2016 Sep
///  \date 2021 Sep
///
///  *********************************************

#ifndef __BACKEND_MACROS_HPP__
#define __BACKEND_MACROS_HPP__

#include <iostream>
#include <string>
#include <map>
#include <sstream>

#include "gambit/Utils/util_macros.hpp"
#include "gambit/Utils/util_types.hpp"
#include "gambit/Utils/util_functions.hpp"
#include "gambit/Elements/module_macros_incore.hpp"
#include "gambit/Elements/functors.hpp"
#include "gambit/Elements/functor_definitions.hpp"
#include "gambit/Logs/logger.hpp"
#include "gambit/Backends/ini_functions.hpp"
#include "gambit/Backends/common_macros.hpp"
#include "gambit/Backends/interoperability.hpp"
#ifndef STANDALONE
  #include "gambit/Core/ini_functions.hpp"
#endif

#include <boost/preprocessor/logical/bitand.hpp>
#include <boost/preprocessor/logical/bitor.hpp>
#include <boost/preprocessor/list/size.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/seq/to_tuple.hpp>
#include <boost/preprocessor/tuple/to_seq.hpp>

/// Macros to add names to an argument list
#define ARG_NAME(R,DATA,INDEX,ELEM) (ELEM arg##INDEX)
#define FUNCTION_ARGS_SEQ(ARGLIST) BOOST_PP_IF(ISEMPTY(ARGLIST), (),                            \
        BOOST_PP_SEQ_FOR_EACH_I(ARG_NAME, , BOOST_PP_TUPLE_TO_SEQ(ARGLIST)))
#define FUNCTION_ARGS(ARGLIST) BOOST_PP_SEQ_TO_TUPLE(FUNCTION_ARGS_SEQ(ARGLIST))

/// Macros to get only the names corresponding to an argument list
#define ARG_NAME_ONLY(R,DATA,INDEX,ELEM) (std::forward<ELEM>(arg##INDEX))
#define FUNCTION_ARG_NAMES_SEQ(ARGLIST) BOOST_PP_IF(ISEMPTY(ARGLIST), (),                       \
        BOOST_PP_SEQ_FOR_EACH_I(ARG_NAME_ONLY, , BOOST_PP_TUPLE_TO_SEQ(ARGLIST)))
#define FUNCTION_ARG_NAMES(ARGLIST) BOOST_PP_SEQ_TO_TUPLE(FUNCTION_ARG_NAMES_SEQ(ARGLIST))

/// Declare the backend initialisation module BackendIniBit.
#define MODULE BackendIniBit
  START_MODULE
#undef MODULE

/// Dependency macro for point-level backend initialisation functions (in BackendIniBit)
#define BE_INI_DEPENDENCY(DEP, TYPE) CORE_DEPENDENCY(DEP, TYPE, BackendIniBit, CAT_5(BACKENDNAME,_,SAFE_VERSION,_,init), NOT_MODEL)

/// Model-conditional dependency macro for point-level backend initialisation functions (in BackendIniBit)
#define BE_INI_CONDITIONAL_DEPENDENCY(DEP, TYPE, ...)                                                                                             \
  CORE_START_CONDITIONAL_DEPENDENCY(BackendIniBit, CAT_5(BACKENDNAME,_,SAFE_VERSION,_,init), CAT_5(BACKENDNAME,_,SAFE_VERSION,_,init), DEP, TYPE, NOT_MODEL) \
  ACTIVATE_DEP_MODEL(BackendIniBit, CAT_5(BACKENDNAME,_,SAFE_VERSION,_,init), CAT_5(BACKENDNAME,_,SAFE_VERSION,_,init), DEP, NOT_MODEL, #__VA_ARGS__)

/// Macro for assigning a single allowed model to an entire backend.
#define BE_ALLOW_MODEL(MODEL)                                               \
BE_NAMESPACE                                                                \
{                                                                           \
  namespace                                                                 \
  {                                                                         \
    const int UNUSED_OK CAT(MODEL,_OK) =                                    \
     vectorstr_push_back(allowed_models,STRINGIFY(MODEL));                  \
  }                                                                         \
}                                                                           \
END_BE_NAMESPACE                                                            \
CORE_ALLOWED_MODEL(BackendIniBit,CAT_4(BACKENDNAME,_,SAFE_VERSION,_init),   \
 MODEL, NOT_MODEL)                                                          \

/// Set all the allowed models for a given backend functor.
#define SET_ALLOWED_MODELS(NAME, MODELS)                                    \
int CAT(allowed_models_set_,NAME) =                                         \
 set_allowed_models(Functown::NAME, allowed_models, STRINGIFY(MODELS));

/// Make the inUse pipe for a given backend functor.
#define MAKE_INUSE_POINTER(NAME)                                            \
  namespace BackendIniBit                                                   \
  {                                                                         \
    namespace Pipes                                                         \
    {                                                                       \
      namespace CAT_4(BACKENDNAME,_,SAFE_VERSION,_init)                     \
      {                                                                     \
        namespace InUse                                                     \
        {                                                                   \
          safe_ptr<bool> NAME = Backends::CAT_3(BACKENDNAME,_,SAFE_VERSION) \
                                ::Functown::NAME.inUsePtr();                \
        }                                                                   \
      }                                                                     \
    }                                                                       \
  }                                                                         \

/// Macro containing initialization code
#define LOAD_LIBRARY                                                        \
namespace Gambit                                                            \
{                                                                           \
  namespace Backends                                                        \
  {                                                                         \
    namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                             \
    {                                                                       \
      std::vector<str> allowed_models;                                      \
                                                                            \
      /* Load the library */                                                \
      int load = backendInfo().loadLibrary(STRINGIFY(BACKENDNAME),          \
                 STRINGIFY(VERSION), STRINGIFY(SAFE_VERSION),               \
                 DO_CLASSLOADING, STRINGIFY(BACKENDLANG));                  \
                                                                            \
      /* Register this backend with the Core if not running in standalone */\
      REGISTER_BACKEND(BACKENDNAME, VERSION, SAFE_VERSION, REFERENCE)       \
                                                                            \
      /* Register a LogTag for this backend with the logging system */      \
      int reg_log = register_backend_with_log(STRINGIFY(BACKENDNAME));      \
                                                                            \
      /* Make backend path easily available to convenience functions. */    \
      extern const str backendDir = backendInfo().                          \
       path_dir(STRINGIFY(BACKENDNAME), STRINGIFY(VERSION));                \
                                                                            \
      /* Make an easy reference to the actual backend module if it is a */  \
      /* Python backend. */                                                 \
      IF_USING_PYBIND11(pybind11::module& BACKENDNAME = backendInfo().      \
       getPythonBackend(STRINGIFY(BACKENDNAME), STRINGIFY(VERSION));)       \
    }                                                                       \
  }                                                                         \
}                                                                           \
                                                                            \
/* Register the factory functions for all classes loaded by this backend. */\
BOOST_PP_IIF(DO_CLASSLOADING, LOAD_ALL_FACTORIES, )                         \
                                                                            \
/* Only do the rest if this is not a data-only backend */                   \
BOOST_PP_IF(DATA_ONLY, ,                                                    \
                                                                            \
/* Register the initialisation function for this backend */                 \
CORE_START_CAPABILITY(BackendIniBit,                                        \
 CAT_4(BACKENDNAME,_,SAFE_VERSION,_init), NOT_MODEL)                        \
CORE_DECLARE_FUNCTION(BackendIniBit,                                        \
 CAT_4(BACKENDNAME,_,SAFE_VERSION,_init),                                   \
 CAT_4(BACKENDNAME,_,SAFE_VERSION,_init),                                   \
 void,2, NOT_MODEL)                                                         \
                                                                            \
namespace Gambit                                                            \
{                                                                           \
  namespace Backends                                                        \
  {                                                                         \
    namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                             \
    {                                                                       \
      /* Disable the initialisation function if the backend is missing */   \
      int ini_status = set_BackendIniBit_functor_status(                    \
       BackendIniBit::Functown::CAT_4(BACKENDNAME,_,SAFE_VERSION,_init),    \
       STRINGIFY(BACKENDNAME), STRINGIFY(VERSION));                         \
    }                                                                       \
  }                                                                         \
}                                                                           \
)


/// Register this backend with the Core if not running in standalone mode.
#ifndef STANDALONE
  #define REGISTER_BACKEND(BE, VER, SAFEVER, REF)                           \
   int CAT_4(BE,_,SAFEVER,_rego) =                                          \
    register_backend(STRINGIFY(BE), STRINGIFY(VER), SAFE_STRINGIFY(REF));
#else
  #define REGISTER_BACKEND(BE, VER, SAFEVER, REF) DUMMYARG(BE, VER, SAFEVER, REF)
#endif

/// Load factory functions for classes provided by this backend
#define LOAD_ALL_FACTORIES                                                                      \
 BOOST_PP_SEQ_FOR_EACH(LOAD_FACTORIES_FOR_TYPE, , CAT_4(BACKENDNAME,_,SAFE_VERSION,_all_data))

/// Load all factory functions for a given type.
#define LOAD_FACTORIES_FOR_TYPE(r,data,elem)                                                    \
namespace Gambit                                                                                \
{                                                                                               \
  namespace Backends                                                                            \
  {                                                                                             \
    namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                                                 \
    {                                                                                           \
      /*Alias the namespace that the classes live in, to avoid macro issues with "::" */        \
      namespace my_ns = ::CAT_3(BACKENDNAME,_,SAFE_VERSION);                                    \
                                                                                                \
      /*Typedef the wrapper type to avoid expanding type seq inside BOOST_PP_SEQ_FOR_EACH_I*/   \
      typedef ::CAT_3(BACKENDNAME,_,SAFE_VERSION)::BOOST_PP_SEQ_FOR_EACH_I(TRAILING_NSQUALIFIER,\
               , BOOST_PP_SEQ_SUBSEQ(BOOST_PP_TUPLE_ELEM(2,0,elem),0,                           \
                BOOST_PP_SUB(BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(2,0,elem)),1)))              \
              BOOST_PP_SEQ_ELEM(BOOST_PP_SUB(BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(2,0,elem)),1)\
               ,BOOST_PP_TUPLE_ELEM(2,0,elem))                                                  \
              CAT(BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_TRANSFORM(APPEND_TOKEN,                         \
               NS_SEP, BOOST_PP_TUPLE_ELEM(2,0,elem))),wrapper);                                \
                                                                                                \
      /*Typedef the abstract type to avoid expanding type seq inside BOOST_PP_SEQ_FOR_EACH_I*/  \
      typedef ::CAT_3(BACKENDNAME,_,SAFE_VERSION)::BOOST_PP_SEQ_FOR_EACH_I(TRAILING_NSQUALIFIER,\
               , BOOST_PP_SEQ_SUBSEQ(BOOST_PP_TUPLE_ELEM(2,0,elem),0,                           \
                BOOST_PP_SUB(BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(2,0,elem)),1)))              \
              CAT(Abstract_,BOOST_PP_SEQ_ELEM(BOOST_PP_SUB(BOOST_PP_SEQ_SIZE(                   \
               BOOST_PP_TUPLE_ELEM(2,0,elem)),1), BOOST_PP_TUPLE_ELEM(2,0,elem)))               \
              CAT(BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_TRANSFORM(APPEND_TOKEN,                         \
         NS_SEP, BOOST_PP_TUPLE_ELEM(2,0,elem))),abstract);                                     \
                                                                                                \
      /*Register the type with the backend info object*/                                        \
      int CAT(registered_type_,BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_TRANSFORM(APPEND_TOKEN,            \
       NS_SEP, BOOST_PP_TUPLE_ELEM(2,0,elem)))) =                                               \
       register_type(STRINGIFY(BACKENDNAME)STRINGIFY(VERSION),                                  \
         STRINGIFY(BOOST_PP_SEQ_FOR_EACH_I(TRAILING_NSQUALIFIER, ,                              \
         BOOST_PP_SEQ_SUBSEQ(BOOST_PP_TUPLE_ELEM(2,0,elem),0,                                   \
         BOOST_PP_SUB(BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(2,0,elem)),1)))                     \
         BOOST_PP_SEQ_ELEM(BOOST_PP_SUB(BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(2,0,elem)),1),    \
         BOOST_PP_TUPLE_ELEM(2,0,elem))));                                                      \
                                                                                                \
    } /* end namespace BACKENDNAME_SAFE_VERSION */                                              \
  } /* end namespace Backends */                                                                \
} /* end namespace Gambit*/                                                                     \
                                                                                                \
/*Load up each factory in turn for this type*/                                                  \
BOOST_PP_SEQ_FOR_EACH_I(LOAD_NTH_FACTORY_FOR_TYPE,                                              \
 BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_TRANSFORM(APPEND_TOKEN, NS_SEP,                                  \
 BOOST_PP_TUPLE_ELEM(2,0,elem))), BOOST_PP_TUPLE_ELEM(2,1,elem))                                \

/// Redirector from within BOOST_PP_SEQ_FOR_EACH_I to LOAD_SINGLE_FACTORY
#define LOAD_NTH_FACTORY_FOR_TYPE(r,data,i,elem)                                                \
 LOAD_SINGLE_FACTORY(data, CAT_3(data,factory,i), BOOST_PP_TUPLE_ELEM(2,1,elem),                \
 BOOST_PP_TUPLE_ELEM(2,0,elem), CAT(data,abstract), CAT(data,wrapper)::CAT(__factory,i) )       \

/// Load a single factory function from a backend
#define LOAD_SINGLE_FACTORY(BARENAME, NAME, ARGS, SYMBOLNAMES, ABSTRACT, PTRNAME)               \
namespace Gambit                                                                                \
{                                                                                               \
  namespace Backends                                                                            \
  {                                                                                             \
    namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                                                 \
    {                                                                                           \
                                                                                                \
      /* Define a type NAME_type to be a suitable function pointer. */                          \
      typedef ABSTRACT*(*CAT(NAME,_type))CONVERT_VARIADIC_ARG(ARGS);                            \
                                                                                                \
      /* Get the pointer to the function in the shared library. */                              \
      extern const CAT(NAME,_type) NAME =                                                       \
       load_backend_symbol<CAT(NAME,_type)>(initVector<str>(STRIP_PARENS(SYMBOLNAMES)),         \
       STRINGIFY(BACKENDNAME), STRINGIFY(VERSION));                                             \
                                                                                                \
      /* Function to throw an error if a backend is absent. */                                  \
      ABSTRACT* CAT(backend_not_loaded_,NAME)CONVERT_VARIADIC_ARG(ARGS)                         \
      {                                                                                         \
        std::ostringstream err;                                                                 \
        err << "The backend library" << std::endl                                               \
            << STRINGIFY(BACKENDNAME) << " v" << STRINGIFY(VERSION) << "," << std::endl         \
            << "which is supposed to contain the factory for class " << std::endl               \
            << fixns(STRINGIFY(BARENAME) STRINGIFY(CONVERT_VARIADIC_ARG(ARGS)))<<", "<<std::endl\
            << "is missing or catastrophically broken." << std::endl                            \
            << "Fix or find that backend yo -- or don't use the type." << std::endl;            \
        backend_error().raise(LOCAL_INFO BOOST_PP_COMMA() err.str());                           \
        return NULL;                                                                            \
      }                                                                                         \
                                                                                                \
      /* Function to throw an error if a factory hasn't loaded properly. */                     \
      ABSTRACT* CAT(factory_not_loaded_,NAME)CONVERT_VARIADIC_ARG(ARGS)                         \
      {                                                                                         \
        std::ostringstream err;                                                                 \
        err << "Factory for class " << fixns(STRINGIFY(BARENAME)                                \
                STRINGIFY(CONVERT_VARIADIC_ARG(ARGS)))                                          \
            << " did not load properly from " << std::endl                                      \
            << STRINGIFY(BACKENDNAME) << " v" << STRINGIFY(VERSION) << std::endl                \
            << "...so you can't make an object with it." << std::endl;                          \
        backend_error().raise(LOCAL_INFO BOOST_PP_COMMA() err.str());                           \
        return NULL;                                                                            \
      }                                                                                         \
                                                                                                \
    }                                                                                           \
  }                                                                                             \
}                                                                                               \
                                                                                                \
namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                                                     \
{                                                                                               \
  /* Define the static function pointer in the wrapper class for this factory. */               \
  Gambit::Backends::CAT_3(BACKENDNAME,_,SAFE_VERSION)::CAT(NAME,_type)                          \
   Gambit::Backends::CAT_3(BACKENDNAME,_,SAFE_VERSION)::PTRNAME =                               \
   Gambit::Backends::handover_factory_pointer(STRINGIFY(BACKENDNAME), STRINGIFY(VERSION),       \
   STRINGIFY(NAME), STRINGIFY(BARENAME), STRINGIFY(CONVERT_VARIADIC_ARG(ARGS)),                 \
   Gambit::initVector<std::string>(STRIP_PARENS(SYMBOLNAMES)),                                  \
   Gambit::Backends::CAT_3(BACKENDNAME,_,SAFE_VERSION)::NAME,                                   \
   &Gambit::Backends::CAT_3(BACKENDNAME,_,SAFE_VERSION)::CAT(backend_not_loaded_,NAME),         \
   &Gambit::Backends::CAT_3(BACKENDNAME,_,SAFE_VERSION)::CAT(factory_not_loaded_,NAME));        \
}                                                                                               \


// Determine whether to make registration calls to the Core or not in BE_VARIABLE_I, depending on STANDALONE flag
#ifdef STANDALONE
  #define BE_VARIABLE_I(NAME, TYPE, SYMBOLNAMES, CAPABILITY, MODELS, REF)           \
          BE_VARIABLE_I_AUX(NAME, TYPE, SYMBOLNAMES, CAPABILITY, MODELS)            \
          BE_VARIABLE_I_MAIN(NAME, MATH_TYPE(TYPE), SYMBOLNAMES, CAPABILITY,        \
                             MODELS, REF)
#else
  #define BE_VARIABLE_I(NAME, TYPE, SYMBOLNAMES, CAPABILITY, MODELS, REF)           \
          BE_VARIABLE_I_AUX(NAME, TYPE, SYMBOLNAMES, CAPABILITY, MODELS)            \
          BE_VARIABLE_I_MAIN(NAME, MATH_TYPE(TYPE), SYMBOLNAMES, CAPABILITY,        \
                             MODELS, REF)                                           \
          BE_VARIABLE_I_SUPP(NAME)
#endif

#define BE_VARIABLE_I_AUX(NAME, TYPE, SYMBOLNAMES, CAPABILITY, MODELS)              \
        IF_ELSEIF(USING_MATHEMATICA, BE_VARIABLE_I_MATH,                            \
                  USING_PYTHON, BE_VARIABLE_I_PY,                                   \
                  BE_VARIABLE_I_OTHER)(NAME, TYPE, SYMBOLNAMES, CAPABILITY, MODELS)

/// Backend variable macro for regular backends (C/C++/Fortran)
#define BE_VARIABLE_I_OTHER(NAME, TYPE, SYMBOLNAMES, CAPABILITY, MODELS)      \
namespace Gambit                                                              \
{                                                                             \
  namespace Backends                                                          \
  {                                                                           \
    namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                               \
    {                                                                         \
                                                                              \
      /* Set the variable pointer and the getptr function. */                 \
      extern TYPE* const NAME =                                               \
       load_backend_symbol<TYPE*>(initVector<str>(STRIP_PARENS(SYMBOLNAMES)), \
       STRINGIFY(BACKENDNAME), STRINGIFY(VERSION));                           \
      TYPE* CAT(getptr,NAME)() { return NAME; }                               \
                                                                              \
    }                                                                         \
  }                                                                           \
}

/// Main actual backend variable macro
#define BE_VARIABLE_I_MAIN(NAME, TYPE, SYMBOLNAMES, CAPABILITY, MODELS, REF)  \
namespace Gambit                                                              \
{                                                                             \
  namespace Backends                                                          \
  {                                                                           \
    namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                               \
    {                                                                         \
      /* Create functor objects */                                            \
      namespace Functown                                                      \
      {                                                                       \
        backend_functor<TYPE*(*)(), TYPE*> NAME(                              \
        Gambit::Backends::CAT_3(BACKENDNAME,_,SAFE_VERSION)::CAT(getptr,NAME),\
        STRINGIFY(NAME),   /* functor name */                                 \
        CAPABILITY,        /* functor capability */                           \
        SAFE_STRINGIFY(TYPE*),                                                \
        STRINGIFY(BACKENDNAME),                                               \
        STRINGIFY(VERSION),                                                   \
        STRINGIFY(SAFE_VERSION),                                              \
        SAFE_STRINGIFY(REF),                                                  \
        Models::ModelDB());                                                   \
      } /* end namespace Functown */                                          \
                                                                              \
      /* Set the allowed model properties of the functor. */                  \
      SET_ALLOWED_MODELS(NAME, MODELS)                                        \
                                                                              \
      /* Disable the functor if the library is missing or symbol not found. */\
      int CAT(vstatus_,NAME) = set_backend_functor_status(Functown::NAME,     \
       initVector<str>(STRIP_PARENS(SYMBOLNAMES)));                           \
                                                                              \
    } /* end namespace BACKENDNAME_SAFE_VERSION */                            \
  } /* end namespace Backends */                                              \
                                                                              \
  /* Create the safe pointer to the 'in use' flag of the functor. */          \
  MAKE_INUSE_POINTER(NAME)                                                    \
                                                                              \
} /* end namespace Gambit */                                                  \

/// Supplementary backend variable macro
#define BE_VARIABLE_I_SUPP(NAME)                                              \
namespace Gambit                                                              \
{                                                                             \
  namespace Backends                                                          \
  {                                                                           \
    namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                               \
    {                                                                         \
      int CAT(vptr_supp_,NAME) = register_backend_functor(Functown::NAME);    \
    }                                                                         \
  }                                                                           \
}                                                                             \


/// \name Wrapping macros for backend-defined functions
///
/// BE_FUNCTION(NAME, TYPE, ARGSLIST, SYMBOLNAMES, CAPABILITY, [(MODELS)], [REF]) is the
/// macro used for constructing pointers to library functions and
/// wrapping function pointers in backend functors.
///
/// The sixth argument (MODELS) is optional, and contains a list of models that you want this function to be able
/// to be used with.
/// The seventh argument REF is optional, and contains a string of citation keys as references for the backend function
/// @{

#define BE_FUNCTION_5(NAME, TYPE, ARGSLIST, SYMBOLNAMES, CAPABILITY)                            \
  BE_FUNCTION_I(NAME, TYPE, ARGSLIST, SYMBOLNAMES, CAPABILITY, (), "")

#define BE_FUNCTION_6(NAME, TYPE, ARGSLIST, SYMBOLNAMES, CAPABILITY, MODELS)                    \
  BE_FUNCTION_I(NAME, TYPE, ARGSLIST, SYMBOLNAMES, CAPABILITY, MODELS, "")

#define BE_FUNCTION_7(NAME, TYPE, ARGSLIST, SYMBOLNAMES, CAPABILITY, MODELS, REF)               \
  BE_FUNCTION_I(NAME, TYPE, ARGSLIST, SYMBOLNAMES, CAPABILITY, MODELS, REF)

#define BE_FUNCTION(...) VARARG(BE_FUNCTION, __VA_ARGS__)


// Determine whether to make registration calls to the Core or not in BE_FUNCTION_IMPL2, depending on STANDALONE flag
#ifdef STANDALONE
  #define BE_FUNCTION_I(NAME, TYPE, ARGLIST, SYMBOLNAMES, CAPABILITY, MODELS, REF)              \
          BE_FUNCTION_I_AUX(NAME, TYPE, ARGLIST, SYMBOLNAMES, CAPABILITY, MODELS)               \
          BE_FUNCTION_I_MAIN(NAME, TYPE, ARGLIST, SYMBOLNAMES, CAPABILITY, MODELS, REF)
#else
  #define BE_FUNCTION_I(NAME, TYPE, ARGLIST, SYMBOLNAMES, CAPABILITY, MODELS, REF)              \
          BE_FUNCTION_I_AUX(NAME, TYPE, ARGLIST, SYMBOLNAMES, CAPABILITY, MODELS)               \
          BE_FUNCTION_I_MAIN(NAME, TYPE, ARGLIST, SYMBOLNAMES, CAPABILITY, MODELS, REF)         \
          BE_FUNCTION_I_SUPP(NAME)
#endif

#define BE_FUNCTION_I_AUX(NAME, TYPE, ARGLIST, SYMBOLNAMES, CAPABILITY, MODELS)                 \
        IF_ELSEIF(USING_MATHEMATICA, BE_FUNCTION_I_MATH,                                        \
                  USING_PYTHON, BE_FUNCTION_I_PY,                                               \
                  BE_FUNCTION_I_OTHER)(NAME, TYPE, ARGLIST, SYMBOLNAMES, CAPABILITY, MODELS)

/// Backend function macro for other backends (C/C++/Fortran)
#define BE_FUNCTION_I_OTHER(NAME, TYPE, ARGLIST, SYMBOLNAMES, CAPABILITY, MODELS)               \
namespace Gambit                                                                                \
{                                                                                               \
  namespace Backends                                                                            \
  {                                                                                             \
    namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                                                 \
    {                                                                                           \
      /* Define a type NAME_type to be a suitable function pointer. */                          \
      typedef TYPE (*NAME##_type) CONVERT_VARIADIC_ARG(ARGLIST);                                \
                                                                                                \
      extern const NAME##_type NAME = load_backend_symbol<NAME##_type>(initVector<str>(         \
      STRIP_PARENS(SYMBOLNAMES)), STRINGIFY(BACKENDNAME), STRINGIFY(VERSION));                  \
                                                                                                \
    }                                                                                           \
  }                                                                                             \
}

/// Main actual backend function macro
#define BE_FUNCTION_I_MAIN(NAME, TYPE, ARGLIST, SYMBOLNAMES, CAPABILITY, MODELS, REF)           \
namespace Gambit                                                                                \
{                                                                                               \
  namespace Backends                                                                            \
  {                                                                                             \
    namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                                                 \
    {                                                                                           \
                                                                                                \
      /* Create functor object */                                                               \
      namespace Functown                                                                        \
      {                                                                                         \
        backend_functor<TYPE(*)CONVERT_VARIADIC_ARG(ARGLIST), TYPE                              \
         INSERT_NONEMPTY(STRIP_VARIADIC_ARG(ARGLIST))> NAME(                                    \
         Gambit::Backends::CAT_3(BACKENDNAME,_,SAFE_VERSION)::NAME,                             \
         STRINGIFY(NAME),                                                                       \
         CAPABILITY,                                                                            \
         STRINGIFY(TYPE) STRINGIFY(CONVERT_VARIADIC_ARG(ARGLIST)),                              \
         STRINGIFY(BACKENDNAME),                                                                \
         STRINGIFY(VERSION),                                                                    \
         STRINGIFY(SAFE_VERSION),                                                               \
         SAFE_STRINGIFY(REF),                                                                   \
         Models::ModelDB());                                                                    \
      } /* end namespace Functown */                                                            \
                                                                                                \
      /* Disable the functor if the library is not present or the symbol not found. */          \
      int CAT(fstatus_,NAME)=set_backend_functor_status(Functown::NAME,                         \
       initVector<str>(STRIP_PARENS(SYMBOLNAMES)));                                             \
                                                                                                \
      /* Set the allowed model properties of the functor. */                                    \
      SET_ALLOWED_MODELS(NAME, MODELS)                                                          \
                                                                                                \
    } /* end namespace BACKENDNAME_SAFE_VERSION */                                              \
  } /* end namespace Backends */                                                                \
                                                                                                \
  /* Create the safe pointer to the 'in use' flag of the functor. */                            \
  MAKE_INUSE_POINTER(NAME)                                                                      \
                                                                                                \
} /* end namespace Gambit*/


/// Supplemenentary backend function macro
#define BE_FUNCTION_I_SUPP(NAME)                                                                \
namespace Gambit                                                                                \
{                                                                                               \
  namespace Backends                                                                            \
  {                                                                                             \
    namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                                                 \
    {                                                                                           \
      int CAT(fptr_supp_,NAME) = register_backend_functor(Functown::NAME);                      \
    }                                                                                           \
  }                                                                                             \
}                                                                                               \


// Determine whether to make registration calls to the Core or not in BE_CONV_FUNCTION, depending on STANDALONE flag
#ifdef STANDALONE
  #define BE_CONV_FUNCTION_FULL(NAME, TYPE, ARGSLIST, CAPABILITY, MODELS, REF)                  \
          BE_CONV_FUNCTION_MAIN(NAME, TYPE, ARGSLIST, CAPABILITY, MODELS, REF)
#else
  #define BE_CONV_FUNCTION_FULL(NAME, TYPE, ARGSLIST, CAPABILITY, MODELS, REF)                  \
          BE_CONV_FUNCTION_MAIN(NAME, TYPE, ARGSLIST, CAPABILITY, MODELS, REF)                  \
          BE_CONV_FUNCTION_SUPP(NAME)
#endif


/// \name Main wrapping macro for convenience functions
/// BE_CONV_FUNCTION(NAME, TYPE, ARGSLIST, CAPABILITY, [(MODELS)], [REF]) is the macro used
/// for wrapping convenience functions in backend functors.
#define BE_CONV_FUNCTION_MAIN(NAME, TYPE, ARGSLIST, CAPABILITY, MODELS, REF)                    \
namespace Gambit                                                                                \
{                                                                                               \
  namespace Backends                                                                            \
  {                                                                                             \
    namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                                                 \
    {                                                                                           \
      /* Forward declare function */                                                            \
      TYPE NAME(STRIP_PARENS(CONVERT_VARIADIC_ARG(ARGSLIST)));                                  \
      /* Create functor object */                                                               \
      namespace Functown                                                                        \
      {                                                                                         \
        backend_functor<TYPE(*)CONVERT_VARIADIC_ARG(ARGSLIST), TYPE                             \
         INSERT_NONEMPTY(STRIP_VARIADIC_ARG(ARGSLIST))> NAME(                                   \
         Gambit::Backends::CAT_3(BACKENDNAME,_,SAFE_VERSION)::NAME,                             \
         STRINGIFY(NAME),                                                                       \
         CAPABILITY,                                                                            \
         STRINGIFY(TYPE) STRINGIFY(CONVERT_VARIADIC_ARG(ARGSLIST)),                             \
         STRINGIFY(BACKENDNAME),                                                                \
         STRINGIFY(VERSION),                                                                    \
         STRINGIFY(SAFE_VERSION)  BOOST_PP_COMMA()                                              \
         SAFE_STRINGIFY(REF),                                                                   \
         Models::ModelDB());                                                                    \
      } /* end namespace Functown */                                                            \
                                                                                                \
      /* Disable the functor if the library is not present or the symbol not found. */          \
      int CAT(fstatus_,NAME) = set_backend_functor_status(Functown::NAME,                       \
       initVector<str>("no_symbol"));                                                           \
                                                                                                \
      /* Set the allowed model properties of the functor. */                                    \
      SET_ALLOWED_MODELS(NAME, MODELS)                                                          \
    }                                                                                           \
  }                                                                                             \
  /* Create the safe pointer to the 'in use' flag of the functor. */                            \
  MAKE_INUSE_POINTER(NAME)                                                                      \
}                                                                                               \

/// \name Supplementary wrapping macro for convenience functions
#define BE_CONV_FUNCTION_SUPP(NAME)                                                             \
namespace Gambit                                                                                \
{                                                                                               \
  namespace Backends                                                                            \
  {                                                                                             \
    namespace CAT_3(BACKENDNAME,_,SAFE_VERSION)                                                 \
    {                                                                                           \
      int CAT(cfptr_supp_,NAME) = register_backend_functor(Functown::NAME);                     \
    }                                                                                           \
  }                                                                                             \
}                                                                                               \

#endif // __BACKEND_MACROS_HPP__

Updated on 2023-06-26 at 21:36:57 +0000