Създаване на функция с препроцесор и прототип на указател на функция

Искам веднъж завинаги да създам хубава и лъскава версия на този подигравки за C код.

Искам да създам макрос на бойлерна плоча като по-долу:

#define MOCK_FREE_FUNCTION(NAME, SIGN, MOCK) \
  /* whatever goes here */

В кода (или заглавката) трябва да се използва така:MOCK_FREE_FUNCTION2(myFunc, void(char *, const char *), myFuncMock); и да се разшири до нещо

struct Whatever_myFunc {
  MOCK_CONST_METHOD2(myFunc, void (char *x, char *y));
};

Whatever_myFunc myFuncMock;

extern "C" {
   void myFunc(char *x, char *y) {
      myFuncMock.(x,y);
   }
}

/* maybe some convenience EXPECT_CALL thing */

Наясно съм, че не всички неща са възможни, но искам да се доближа възможно най-близо до това. Докато линкерът не се оплаква и намира своите символи, аз също няма да се оплаквам. И нямам нищо против, ако са два различни макроса: единият за дефиниране на статичните членове, а другият за прототипите.

Допълнение от коментар

генерирането на повечето неща е лесно, проблемът, който не свършвам, е как gmock успява да получи от

MOCK_METHOD2(foo, void(char *, char*)

до нещо като void foo(char *, char*)

Това е най-близкото нещо, което мога да измисля:

#include <stdio.h>

#define MOCK_FREE_FUNCTION2(NAME, MOCK, RET, ARGS) \
  typedef RET (*NAME ## Type) ARGS; \
  NAME ## Type NAME = barfoo_f;

/* ok it's callable, but how do I get my own code inside here? */
void barfoo_f(int i, int j) {
  printf ("hello world %d %d\n", i, j);
}

// How does google mock get rid of , in the prototype
MOCK_FREE_FUNCTION2(FooBar, XXX, void, (int,int));

int main(int argc, char **argv) {
  FooBar(1,2);
}

person Alexander Oh    schedule 15.04.2014    source източник
comment
Моля, покажете опита си, за да можем да ви помогнем да го поправите.   -  person Barmar    schedule 15.04.2014
comment
@Barmar: ето нещо. Не съм разбрал как да вмъкна собствения си код. И нямам представа как всъщност мога да предам google-mock like подпис, докато все още се разширява до нещо, което линкерът ще приеме като символ.   -  person Alexander Oh    schedule 15.04.2014


Отговори (1)


Възможен начин за справяне с вашия близък проблем (как да стигнете от MACRO(foo, void(char*, char*)) до void foo(char*, char*)) може да бъде в комбинация с функционални характеристики:

template <typename F>
struct func_traits;

template <typename R, typename... Args>
struct func_traits<R(Args...)>
{
    using return_type = R;

    template <size_t I>
    using arg_type = typename std::tuple_element<I, std::tuple<Args...>>::type;
};

#define MACRO_2(NAME, TYPE)                                                  \
    func_traits<TYPE>::return_type NAME(func_traits<TYPE>::arg_type<0> arg0, \
                                        func_traits<TYPE>::arg_type<1> arg1)

(Просто използвам std::tuple като бърз начин за внедряване на списъци с типове тук.)

person Oktalist    schedule 15.04.2014