Automatic C wrappers for C ++ functions

Let's say I have an undefined type called variant

as well as two functions to convert to / from that type with the following signature:

struct converter
{
  template<typename T>
  static variant to(const T&);

  template<typename T>
  static T from(const variant&);
};

      

Now what I would like to do is create wrappers for any C ++ functions like in the following example:

SomeObject f_unwrapped(const std::string& s, int* x)
{
    //... do something with the inputs... 
    return SomeObject();
}

extern "C" variant f(variant s, variant x)
{
   return converter::to<SomeObject>(f_unwrapped(converter::from<std::string>(s), converter::from<int*>(x)));
}

      

Ideally, I would like the wrapper to be a one-line declaration or a macro that only takes a function f_unwrapped

and a name as input f

.

I tried to wrap a function in a function object and then do the bureaucratic work using variadic templates. While this does work, I have no idea how to create the resulting function extern "C"

.

What is the most idiomatic way to achieve this goal?

+3


source to share


1 answer


If we use the EVAL, helper, Conditional and map macros from the first two code blocks here .

The map needs to be made more general for our needs.

#define MM1() MM_CALL1
#define MM_NEXT1(Macro,a,...)      \
  IS_DONE(a)(                       \
     EAT                             \
  ,                                   \
     OBSTRUCT(COMMA)() OBSTRUCT(MM1)() \
  )                                     \
  (Macro,a,__VA_ARGS__)
#define MM_CALL1(Macro,a,...)   \
  Macro(a)                       \
  MM_NEXT1(Macro,__VA_ARGS__)
#define MacroMap1(Macro,...) MM_CALL1(Macro,__VA_ARGS__,DONE)

#define MM2() MM_CALL2
#define MM_NEXT2(Macro,a,...)      \
  IS_DONE(a)(                       \
     EAT                             \
  ,                                   \
     OBSTRUCT(COMMA)() OBSTRUCT(MM2)() \
  )                                     \
  (Macro,a,__VA_ARGS__)
#define MM_CALL2(Macro,a,b,...)   \
  Macro(a,b)                       \
  MM_NEXT2(Macro,__VA_ARGS__)
#define MacroMap2(Macro,...) MM_CALL2(Macro,__VA_ARGS__,DONE)

      

We also want to WithTypes

and WithoutTypes

from here .

We can determine AMACRO

to complete the desired task.

#define AsVariant(param) variant param
#define ConvertFrom(type,param) converter::from<type>(param)
#define HEADDER(type,func,params) type func ##_unwrapped (WithTypes params)
#define WRAPPER(type,func,params) \
   extern "C" variant func (OBSTRUCT(MacroMap1)(AsVariant,WithoutTypes params)) \
   { \
   return converter::to< type >(func ## _unwrapped( \
         MacroMap2(ConvertFrom,IDENT params) \
      )); \
   }

#define AMACRO(type,func,params) \
  EVAL(                           \
    HEADDER(type,func,params);     \
    WRAPPER(type,func,params)       \
    HEADDER(type,func,params)        \
  )

      



Which will look like this:

AMACRO(SomeObject,f,(const std::string&, s, int*, x))
{
     // ... do something with the inputs ...
     return SomeObject();
}

      

Into this (after formatting):

SomeObject f_unwrapped (const std::string& s , int* x );

extern "C" variant f (variant s , variant x )
{
   return converter::to<SomeObject>(f_unwrapped(converter::from<const std::string&>(s),converter::from<int*>(x)));
}

SomeObject f_unwrapped (const std::string& s , int* x )
{
   return SomeObject();
}

      

Note: If you const

want to remove from a parameter, a conditional, similar ISDONE

, you can make and add to the macro ConvertFrom

.

0


source







All Articles