I have the following boost preprocessor macro to generate a function
extern "C" EXPORT out name(BOOST_PP_SEQ_FOR_EACH_I(PARAMETER_LIST, 0, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)))
This works great unless if __VA_ARGS__ is empty. After some searching I found a way to count the numer of arguments in __VA_ARGS__ using BOOST_PP_VARIADIC_SIZE. After some thinking I wrote this MACRO:
extern "C" EXPORT out name(BOOST_PP_IF(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), BOOST_PP_SEQ_FOR_EACH_I(PARAMETER_LIST, 0, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)), void))
I think this should work, however I keep getting the following warning
warning C4002: too many actual parameters for macro 'BOOST_PP_IIF_1'
Although this is a warning it still seems to break the preprocessor. When passing multiple arguments it will only process the first one. I find this so strange, how will adding this if break everything is such a weird way? I've checked the comma's and brackets hundred times but they seem fine. How can I fix this preprocessor?
http://www.boost.org/doc/libs/1_54_0/libs/preprocessor/doc/ref/if.html
Edit: this regression seems relevant: https://svn.boost.org/trac/boost/ticket/8606
implementation:
#include <boost/preprocessor.hpp>
// based on the: http://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments
#define __ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) _15
#define __HAS_COMMA(...) __ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
#define __TRIGGER_PARENTHESIS_(...) ,
#define __PASTE5(_0, _1, _2, _3, _4) _0 ## _1 ## _2 ## _3 ## _4
#define __IS_EMPTY_CASE_0001 ,
#define __IS_EMPTY(_0, _1, _2, _3) __HAS_COMMA(__PASTE5(__IS_EMPTY_CASE_, _0, _1, _2, _3))
#define TUPLE_IS_EMPTY(...) \
__IS_EMPTY( \
/* test if there is just one argument, eventually an empty one */ \
__HAS_COMMA(__VA_ARGS__), \
/* test if _TRIGGER_PARENTHESIS_ together with the argument adds a comma */ \
__HAS_COMMA(__TRIGGER_PARENTHESIS_ __VA_ARGS__), \
/* test if the argument together with a parenthesis adds a comma */ \
__HAS_COMMA(__VA_ARGS__ (/*empty*/)), \
/* test if placing it between _TRIGGER_PARENTHESIS_ and the parenthesis adds a comma */ \
__HAS_COMMA(__TRIGGER_PARENTHESIS_ __VA_ARGS__ (/*empty*/)) \
)
#define __GEN_EMPTY_ARGS(...) \
void
#define __GEN_NONEMPTY_ARGS_CB(unused, data, idx, elem) \
BOOST_PP_COMMA_IF(idx) elem arg##idx
#define __GEN_NONEMPTY_ARGS(seq) \
BOOST_PP_SEQ_FOR_EACH_I( \
__GEN_NONEMPTY_ARGS_CB \
,~ \
,seq \
)
#define GEN(out, name, ...) \
extern "C" EXPORT out name( \
BOOST_PP_IF( \
TUPLE_IS_EMPTY(__VA_ARGS__) \
,__GEN_EMPTY_ARGS \
,__GEN_NONEMPTY_ARGS \
)(BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))) \
) {}
// test
GEN(void, finc0, int, char, long)
GEN(void, func1)
output:
extern "C" EXPORT void finc0( int arg0 , char arg1 , long arg2 ) {}
extern "C" EXPORT void func1( void ) {}
Related
After understanding that GCC supports Compound Literals, where an anonymous structure can be filled using a {...} initaliser.
Then consider that gcc accepts (with limitations) variable length structures if the last element is variable length item.
I would like to be able to use macros to fill out lots of tables where most of the data stays the same from compile time and only a few fields change.
My structure are complicated, so here is a simpler working example to start with as a demonstration of the how it is to be used.
#include <stdio.h>
typedef unsigned short int uint16_t;
typedef unsigned long size_t;
#define CONSTANT -20
// The data we are storing, we don't need to fill all fields every time
typedef struct dt {
uint16_t a;
const int b;
} data_t;
// An incomplete structure definiton that matches the general shape
typedef struct ct {
size_t size;
data_t data;
char name[];
} complex_t;
// A typedef to make the code look cleaner
typedef complex_t * complex_t_ptr;
// A macro to generate instances of objects
#define CREATE(X, Y) (complex_t_ptr)&((struct { \
size_t size; \
data_t data; \
char name[sizeof(X)]; \
} ) { \
.size = sizeof(X), \
.data = { .a = Y, .b = CONSTANT }, \
.name = X \
})
// Create an array number of structure instance and put pointers those objects into an array
// Note each object may be a different size.
complex_t_ptr data_table[] = {
CREATE("DATA1", 1),
CREATE("DATA2_LONGER", 2),
CREATE("D3S", 3),
};
static size_t DATA_TABLE_LEN = sizeof(data_table) / sizeof(typeof(0[data_table]));
int main(int argc, char **argv)
{
for(uint16_t idx=0; idx<DATA_TABLE_LEN; idx++)
{
complex_t_ptr p = data_table[idx];
printf("%15s = (%3u, %3d) and is %3lu long\n", p->name, p->data.a, p->data.b, p->size);
}
return 0;
}
$ gcc test_macro.c -o test_macro
$ ./test_macro
DATA1 = ( 1, -20) and is 6 long
DATA2_LONGER = ( 2, -20) and is 13 long
D3S = ( 3, -20) and is 4 long
So far so good...
Now, what if we want to create a more complicated object?
//... skipping the rest as hopefully you have the idea by now
// A more complicated data structure
typedef struct dt2 {
struct {
unsigned char class[10];
unsigned long start_address;
} xtra;
uint16_t a;
const int b;
} data2_t;
// A macro to generate instances of objects
#define CREATE2(X, Y, XTRA) (complex2_t_ptr)&((struct { \
size_t size; \
data2_t data; \
char name[sizeof(X)]; \
} ) { \
.size = sizeof(X), \
.data = { .xtra = XTRA, .a = Y, .b = CONSTANT }, \
.name = X \
})
// Again create the table
complex2_t_ptr bigger_data_table[] = {
CREATE2("DATA1", 1, {"IO_TBL", 0x123456L}),
CREATE2("DATA2_LONGER", 2, {"BASE_TBL", 0xABC123L}),
CREATE2("D3S", 3, {"MAIN_TBL", 0x555666L << 2}),
};
//...
But there is a probem. This does not compile as the compiler (preprocessor) gets confused by the commas between the structure members.
The comma in the passed structure members is seen by the macro and it thinks there are extra parameters.
GCC says you can put brackets round terms where you want to keep the commas, like this
MACRO((keep, the, commas))
e.g. In this case, that would be
CREATE_EXTRA("DATA1", 1, ({"IO_TBL", 0x123456L}) )
But that would not work with a structure as we'd get
.xtra = ({"IO_TBL", 0x123456L})
Which is not a valid initaliser.
The other option would be
CREATE_EXTRA("DATA1", 1, {("IO_TBL", 0x123456L)} )
Which results in
.xtra = {("IO_TBL", 0x123456L)}
Which is also not valid
And if we put the braces inside the macro
.xtra = {EXTRA}
...
CREATE_EXTRA("DATA1", 1, ("IO_TBL", 0x123456L) )
We get the same
Obviously some might say "just pass the elements of XTRA one at a time".
Remember this is a simple, very cut down, example and in practice doing that would lose information and make the code much harder to understand, it would be harder to maintain but easer to read if the structures were just copied out longhand.
So the question is, "how to pass compound literal structures to macros as initalisers without getting tripped up by the commas between fields".
NOTE I am stuck with C11 on GCC4.8.x, so C++ or any more recent GCC is not possible.
So there is a way, though I can't find it meantioned on the GCC pages for Macros.
I found what I needed in this article: Comma omission and comma deletion
The following works.
typedef struct _array_data {
size_t size;
char * data;
}array_data_t;
#define ARRAY_DATA(ARRAY...) (char *) \
&(array_data_t) { \
sizeof((char []){ARRAY}), \
(char []){ARRAY} \
}
char * my_array = ARRAY_DATA(1,2,3,4);
size_t sent = send_packet(my_array);
if (len != my_array->size) ERROR("Not all data sent");
There are some interesting aspects to this.
1: Unlike the example in the gcc manual, the brackets are omitted round the {ARRAY}. In the document, the example uses (cast)({structure}) rather than (cast){structure}. In fact it looks like the brackets are never needed and just confuse the compiler in some cases (like when you take the address).
2: The use of the cast (char []) rather than (char *) as one would have thought to be correct.
3: Of course it makes sense but you have to put a cast round the sizeof part too, as otherwise how would it know the size of the individual literals.
For completeness, the macro in the example above expands to:
char * my_array = (char *)&(array_data_t) { \
sizeof((char []){1,2,3,4}),
(char []){1,2,3,4};
}
Any my_array is a pointer to a structure that looks like this.
* my_array = {
size_t size = 4,
char data[4] = {1,2,3,4}
}
v9.6, win server 2012, vs 2015
successfully compiled and linked as x64.
Create function fails saying that there is no 'add_one' function in the dll.
postgres=# create function add_one(integer) returns integer as
'win32project1',' add_one' language c strict;
ERROR: could not find function "add_one" in file "C:/Program Files/PostgreSQL/9.6/lib/win32project1.dll"
The function seems to be there though, dumpbin says
1 0 000112CB Pg_magic_func = #ILT+710(Pg_magic_func)
2 1 00011087 pg_finfo_add_one = #ILT+130(pg_finfo_add_one)
3 2 00011190 pg_finfo_add_one_float8 = #ILT+395(pg_finfo_add_one_float8)
4 3 000110F5 pg_finfo_concat_text = #ILT+240(pg_finfo_concat_text)
5 4 000112C1 pg_finfo_copytext = #ILT+700(pg_finfo_copytext)
6 5 0001107D pg_finfo_makepoint = #ILT+120(pg_finfo_makepoint)
OK, there needs to be 2 functions exported for each function, the meta data function pg_finfo_xxx plus the actual function itself xxx.
The standard headers for pg functions compiling mark the meta data function with PGDLLEXPORT but the forward declaration of the actual function is not marked that way. I dont see how this could ever work.
#define PG_FUNCTION_INFO_V1(funcname) \
Datum funcname(PG_FUNCTION_ARGS); \
extern PGDLLEXPORT const Pg_finfo_record * CppConcat(pg_finfo_,funcname)(void); \
const Pg_finfo_record * \
CppConcat(pg_finfo_,funcname) (void) \
{ \
static const Pg_finfo_record my_finfo = { 1 }; \
return &my_finfo; \
} \
extern int no_such_variable
But I made it work by doing
#define PG_FUNCTION_INFO_V1(funcname) \
PGDLLEXPORT Datum funcname(PG_FUNCTION_ARGS); \
extern PGDLLEXPORT const Pg_finfo_record * CppConcat(pg_finfo_,funcname)(void); \
const Pg_finfo_record * \
CppConcat(pg_finfo_,funcname) (void) \
{ \
static const Pg_finfo_record my_finfo = { 1 }; \
return &my_finfo; \
} \
extern int no_such_variable
You didn't show your source file, but it should contain this:
extern PGDLLEXPORT Datum add_one(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(add_one);
Then it will probably work.
I have started a discussion on the hackes mailing list to implement your answer in PostgreSQL, but it seems that with the build process that PostgreSQL is using (generate and use export definition files) this causes at least warnings, so we have given up on it.
The other option you have is to create and use an export definition file like PostgreSQL does, then you can do without the PGDLLEXPORT decorations altogether.
I want to run a google/benchmark on float, double and long double.
Given the BENCHMARK_TEMPLATE example, I attempted the following:
#include <cmath>
#include <ostream>
#include <random>
#include <benchmark/benchmark.h>
template<typename Real>
BM_PowTemplated(benchmark::State& state) {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<Real> dis(1, 10);
auto s = dis(gen);
auto t = dis(gen);
Real y;
while (state.KeepRunning()) {
benchmark::DoNotOptimize(y = std::pow(s, t));
}
std::ostream cnull(0);
cnull << y;
}
BENCHMARK_TEMPLATE(BM_PowTemplated, float, double, long double);
BENCHMARK_MAIN();
I imagined that this would then create three benchmarks for float, double and long double, but instead it doesn't compile!
What is the proper syntax for creating templated google benchmarks? Is my mental model for how BENCHMARK_TEMPLATE should work correct and if so how can I fix this code?
You use BENCHMARK_TEMPLATE in wrong way with your
BENCHMARK_TEMPLATE(BM_PowTemplated, float, double, long double);
The readme file of https://github.com/google/benchmark/ says
template <class Q> int BM_Sequential(benchmark::State& state) { .. }
BENCHMARK_TEMPLATE(BM_Sequential, WaitQueue<int>)->Range(1<<0, 1<<10);
Three macros are provided for adding benchmark templates.
#define BENCHMARK_TEMPLATE(func, ...) // Takes any number of parameters.
#define BENCHMARK_TEMPLATE1(func, arg1)
#define BENCHMARK_TEMPLATE2(func, arg1, arg2)
So, BENCHMARK_TEMPLATE with arg1 is used for functions with one template parameter, with arg1 and arg2 for functions with two template parameters. Your BM_PowTemplated has only one parameter, so you can't use BENCHMARK_TEMPLATE with 3 args.
Check test/cxx03_test.cc of google/benchmark for example: https://github.com/google/benchmark/blob/b2e734087532897b7bb4c51a6b4f503060c9a20f/test/cxx03_test.cc
template <class T, class U>
void BM_template2(benchmark::State& state) {
BM_empty(state);
}
BENCHMARK_TEMPLATE2(BM_template2, int, long);
template <class T>
void BM_template1(benchmark::State& state) {
BM_empty(state);
}
BENCHMARK_TEMPLATE(BM_template1, long);
BENCHMARK_TEMPLATE1(BM_template1, int);
PS: definition of macro:
https://github.com/google/benchmark/blob/2d088a9f2d41acb77afc99d045f669e1a21b61ef/include/benchmark/benchmark_api.h#L684
We can see that a (a, b) arguments of macro goes inside < and >, and they are used as f< a,b >:
// template<int arg>
// void BM_Foo(int iters);
//
// BENCHMARK_TEMPLATE(BM_Foo, 1);
//
// will register BM_Foo<1> as a benchmark.
#define BENCHMARK_TEMPLATE1(n, a) \
BENCHMARK_PRIVATE_DECLARE(n) = \
(::benchmark::internal::RegisterBenchmarkInternal( \
new ::benchmark::internal::FunctionBenchmark(#n "<" #a ">", n<a>)))
#define BENCHMARK_TEMPLATE2(n, a, b) \
BENCHMARK_PRIVATE_DECLARE(n) = \
(::benchmark::internal::RegisterBenchmarkInternal( \
new ::benchmark::internal::FunctionBenchmark( \
#n "<" #a "," #b ">", n<a, b>)))
#define BENCHMARK_TEMPLATE(n, ...) \
BENCHMARK_PRIVATE_DECLARE(n) = \
(::benchmark::internal::RegisterBenchmarkInternal( \
new ::benchmark::internal::FunctionBenchmark( \
#n "<" #__VA_ARGS__ ">", n<__VA_ARGS__>)))
So, BENCHMARK_TEMPLATE can't iterate over several variants and define several variants of you function from one line.
I want to use SPI1 on a 18F series PIC as master and then use SPI2 on the same PIC as a slave to another PIC ? Can this be done ?
Yes it can. In fact there would be little point providing two serial modules if you were then constrained to use them in the same way.
As it says in the datasheet:
Note that each operates independently from the other. Also, for each module in SPI mode:
You can see that both master and slave modes are supported.
Each MSSP module has its own set of registers, which are used to configure each module as required.
I use the AD7793 as well, but I've rolled my own SPI_READ and SPI_WRITE macros. These macros work on 16-bit processors, and maybe on 32-bit (I have not tried). The first parameter passed is the SPI port number (e.g. 1 or 2). They work in slave and master mode.
e.g. SPI_WRITE(1, 'H'); or SPI_READ(2, char_to_send, char_to_receive_data);
#define _SPI_WRITE_final(_SPIBUF, _SPIRBF, _SPIROV, ch) \
_SPIROV = 0; \
while (_SPIRBF) \
__asm__ volatile ("mov %0, w0" : : "g"(_SPIBUF) : "cc", "w0"); \
_SPIBUF = (uint8_t)(ch); \
__asm__ volatile ("nop"); \
while (!_SPIRBF);
#define _SPI_WRITE_int(bus, ch) \
_SPI_WRITE_final(SPI##bus##BUF, SPI##bus##STATbits.SPIRBF, \
SPI##bus##STATbits.SPIROV, ch)
#define _SPI_WRITE(bus, ch) do {_SPI_WRITE_int(bus, ch);} while(0)
#define _SPI_READ_final(_SPIBUF, _SPIRBF, _SPIROV, ch_out, ch_in) \
_SPIROV = 0; \
while (_SPIRBF) \
__asm__ volatile ("mov %0, w0" : : "g"(_SPIBUF) : "cc", "w0"); \
_SPIBUF = (uint8_t)(ch_out); \
__asm__ volatile ("nop"); \
while (!_SPIRBF); \
ch_in = _SPIBUF;
#define _SPI_READ_int(bus, ch_out, ch_in) \
_SPI_READ_final(SPI##bus##BUF, SPI##bus##STATbits.SPIRBF, \
SPI##bus##STATbits.SPIROV, ch_out, ch_in)
#define _SPI_READ(bus, ch_out, ch_in) do {_SPI_READ_int(bus, ch_out, ch_in);} while(0)
I would like to know the meaning of %P3 in the following code:
#define get_user(x, ptr) \
({ \
int __ret_gu; \
register __inttype(*(ptr)) __val_gu asm("%edx"); \
__chk_user_ptr(ptr); \
might_fault(); \
asm volatile("call __get_user_%P3" \
: "=a" (__ret_gu), "=r" (__val_gu) \
: "0" (ptr), "i" (sizeof(*(ptr)))); \
(x) = (__typeof__(*(ptr))) __val_gu; \
__ret_gu; \
})
Moreover in the LLVM IR the code is mapped to:
call { i32*, i64 } asm sideeffect "call __get_user_${3:P}", "={ax},={edx},0,i,~{dirflag},~{fpsr},~{flags}"(i32* %tmp73, i64 4)
My understanding is that this is actually calling a specific function __get_user_X in arch/x86/lib/getuser.S, but it's not clear which one in particular (__get_user_4?).
Finally, I would like to understand the difference between %P and %p.
I think %P3 indicates that the X in __get_user_X is depend on "i" (sizeof((ptr)). Such as sizeof((ptr)) may be 1, 2, 4, 8.
The 3 means the third parameter inside the asm volatile("...") statement. And %P is for string concatenation.
About %P and %p difference, I guess it's for string specification, but I am not sure. I copied following sentences from GCC user manual:
%p Substitutes the standard macro predefinitions for the current target machine.
Use this when running cpp.
%P Like ‘%p’, but puts ‘__’ before and after the name of each predefined macro,
except for macros that start with ‘__’ or with ‘_L’, where L is an uppercase
letter. This is for ISO C.