Domanda

I want to once and for all create a nice and shiny version of this mocks for C code.

I want to create a boiler plate macro like below:

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

In the code (or header) it should be used like this:MOCK_FREE_FUNCTION2(myFunc, void(char *, const char *), myFuncMock); and expand to something

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 */

I'm well aware that not all things are possible, but I want to get as close to this as it gets. As long as the linker doesn't complain and finds its symbols I will not complain either. And I don't mind if it's two different macros: one to define the static members and the other for the prototypes.

Addition from the Comment

generating most of the stuff is easy the problem I don't get done is how gmock manages to get from

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

to something like void foo(char *, char*)

This is the closest thing that I could come up with:

#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);
}
È stato utile?

Soluzione

A possible way to address your proximate problem (how to get from MACRO(foo, void(char*, char*)) to void foo(char*, char*)) could be in combination with function traits:

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)

(I'm just using std::tuple as a quick way to implement typelists here.)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top