-
Notifications
You must be signed in to change notification settings - Fork 6
02 Customizing Method Names
Let's expand our simple Hello class to take arguments. And because it's C++ we'll implement different argument types as overloads
#pragma once
#include <iostream>
namespace hello {
class Hello {
public:
void hello(const char* msg) const {
std::cout << "Hello, " << msg << "!\n";
}
void hello(const int msg) const { std::cout << "Hello, " << msg << "!\n"; }
void hello(const float msg) const {
std::cout << "Hello, " << msg << "!\n";
}
};
} // namespace hello
We'll create a new working directory and save this as 02_customizing_methods/include/hello.hpp
.
Next we'll need to update our binding file to match the new method signiatures
#include "hello.hpp"
namespace cppmm_bind {
namespace hello {
struct Hello {
using BoundType = ::hello::Hello;
void hello(const char* msg) const;
void hello(const int msg) const;
void hello(const float msg) const;
};
} // namespace hello
} // namespace cppmm_bind
and we'll save this as 02_customizing_methods/bind/c-hello.cpp
.
If we now generate the AST and the bindings:
./astgen/astgen 02_customizing_methods/bind/c-hello.cpp -v 1 -o 02_customizing_methods/ast -- -I../tutorial/02_customizing_methods/include
./asttoc/asttoc 02_customizing_methods/ast -o 02_customizing_methods -p customizing_methods
and inspect the resulting C header, 02_customizing_methods/customizing_methods-c/c-hello.h
, we can see that asttoc
has renamed the methods for us to avoid name collisions. The names aren't exactly helpful though:
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef struct hello__Hello_t_s {
char data[1];
} __attribute__((aligned(1))) hello__Hello_t;
typedef hello__Hello_t hello_Hello_t;
void hello__Hello_hello(
hello_Hello_t const * this_
, char const * msg);
#define hello_Hello_hello hello__Hello_hello
void hello__Hello_hello_1(
hello_Hello_t const * this_
, int const msg);
#define hello_Hello_hello_1 hello__Hello_hello_1
void hello__Hello_hello_2(
hello_Hello_t const * this_
, float const msg);
#define hello_Hello_hello_2 hello__Hello_hello_2
#ifdef __cplusplus
}
#endif
Fortunately, astgen
lets us add attributes to the binding file to tweak the generated binding in a number of ways, including renaming methods. This is done with standard clang/gcc attributes, and they're wrapped up in macros to make them easier to use.
These macros are defined in a virtual file that's injected by astgen
automatically, called cppmm_bind.hpp
, so the first thing to do is to modify the binding file to include this virtual header, and then we can use the CPPMM_RENAME
macro to specify what name we want for each overload. For example:
#include "hello.hpp"
#include <cppmm_bind.hpp>
namespace cppmm_bind {
namespace hello {
struct Hello {
using BoundType = ::hello::Hello;
void hello(const char* msg) const CPPMM_RENAME(hello_string);
void hello(const int msg) const CPPMM_RENAME(hello_int);
void hello(const float msg) const CPPMM_RENAME(hello_float);
};
} // namespace hello
} // namespace cppmm_bind
and re-running the ast and binding generation as above gives us
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef struct hello__Hello_t_s {
char data[1];
} __attribute__((aligned(1))) hello__Hello_t;
typedef hello__Hello_t hello_Hello_t;
void hello__Hello_hello_string(
hello_Hello_t const * this_
, char const * msg);
#define hello_Hello_hello_string hello__Hello_hello_string
void hello__Hello_hello_int(
hello_Hello_t const * this_
, int const msg);
#define hello_Hello_hello_int hello__Hello_hello_int
void hello__Hello_hello_float(
hello_Hello_t const * this_
, float const msg);
#define hello_Hello_hello_float hello__Hello_hello_float
#ifdef __cplusplus
}
#endif
Much better!