GObject Compilation Error in Macro Expansion While Defining Class - c

Problem
Using GObject and C, I am trying to create a subclass of the class GObject named "Bar" in module "Foo". However, the macro "G_DECLARE_FINAL_TYPE" (defined in gobject/gtype.h) expands incorrectly. Instead of expanding into FOO_BAR, it expands into nothing. So instead of expanding into:
... FooBar * FOO_BAR (gpointer ptr) { ...
It instead expands into:
... FooBar * (gpointer ptr) { ...
Error Message
I expect it to compile but instead gcc gives a syntax error:
In file included from /usr/include/glib-2.0/gobject/gobject.h:24,
from /usr/include/glib-2.0/gobject/gbinding.h:29,
from /usr/include/glib-2.0/glib-object.h:22,
from foo-bar.h:4,
from foo-bar.c:1:
/usr/include/glib-2.0/gobject/gtype.h:1407:77: error: expected ‘)’ before ‘ptr’
1407 | USED static inline ModuleObjName * MODULE##_##OBJ_NAME (gpointer ptr) { \
| ^~~
foo-bar.h:10:1: note: in expansion of macro ‘G_DECLARE_FINAL_TYPE’
10 | G_DECLARE_FINAL_TYPE (FooBar, foo_bar, FOO, BAR, GObject)
| ^~~~~~~~~~~~~~~~~~~~
Definition of Macro
This definition comes from the glib 2.66.7 library. I did not define it myself. I include it for the sake of completeness.
#define G_DECLARE_FINAL_TYPE(ModuleObjName, module_obj_name, MODULE, OBJ_NAME, ParentName) \
GType module_obj_name##_get_type (void); \
G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
typedef struct _##ModuleObjName ModuleObjName; \
typedef struct { ParentName##Class parent_class; } ModuleObjName##Class; \
\
_GLIB_DEFINE_AUTOPTR_CHAINUP (ModuleObjName, ParentName) \
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ModuleObjName##Class, g_type_class_unref) \
\
G_GNUC_UNUSED static inline ModuleObjName * MODULE##_##OBJ_NAME (gpointer ptr) { \
return G_TYPE_CHECK_INSTANCE_CAST (ptr, module_obj_name##_get_type (), ModuleObjName); }\
G_GNUC_UNUSED static inline gboolean MODULE##_IS_##OBJ_NAME (gpointer ptr) { \
return G_TYPE_CHECK_INSTANCE_TYPE (ptr, module_obj_name##_get_type ()); } \
G_GNUC_END_IGNORE_DEPRECATIONS
Partial Pre-Processor Output
I included the definition that contains the syntax error and formatted it for readability:
__attribute__((__unused__)) static inline FooBar * (gpointer ptr) {
return (((FooBar*) g_type_check_instance_cast ((GTypeInstance*) (ptr), (foo_bar_get_type ()))));
}
What's odd is that the definition following does get pre-processed correctly:
__attribute__((__unused__)) static inline gboolean FOO_IS_BAR (gpointer ptr) {
return ((__extension__ ({
GTypeInstance *__inst = (GTypeInstance*) (ptr);
GType __t = (foo_bar_get_type ());
gboolean __r;
if (!__inst) __r = (0);
else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0));
else __r = g_type_check_instance_is_a (__inst, __t); __r; })));
}
Full Minimal Example
I have included a minimal example that causes my error below.
foo-bar.h
#ifndef FOO_BAR
#define FOO_BAR
#include <glib-object.h>
G_BEGIN_DECLS
#define FOO_TYPE_BAR (foo_bar_get_type ())
G_DECLARE_FINAL_TYPE (FooBar, foo_bar, FOO, BAR, GObject)
G_END_DECLS
#endif /* FOO_BAR */
foo-bar.c
#include "foo-bar.h"
struct _FooBar
{
GObject parent_instance;
};
G_DEFINE_TYPE (FooBar, foo_bar, G_TYPE_OBJECT);
static void foo_bar_class_init (FooBarClass *klass)
{
}
static void foo_bar_init (FooBar *app)
{
}
makefile
foo-bar.o: foo-bar.c
gcc -c foo-bar.c $(shell pkg-config --cflags gobject-2.0) -o foo-bar.o
# included to debug the macro
foo-bar.pp: foo-bar.c
gcc -E foo-bar.c $(shell pkg-config --cflags gobject-2.0) -o foo-bar.pp
Versions
glib 2.66.7
gcc 10.2.1
Linux (Fedora 33)
What I have tried
I have studied glib's documentation on how to create a new class and as far as I can tell I am doing it correctly. I have also looked up how token pasting and macro expansion work, and also tried googling my error. It must be something obvious, but I cannot figure out what. I also tried declaring a derivable class with private data, but while finding a minimal example I changed it to a final class without private data and still have the same error. I read about the ## operator here and still cannot tell what is going wrong.
Related Stack Overflow Questions
Finally, I have looked at the following related stackoverflow posts:
My error is that concatenated tokens are not being emitted by the pre-processor. In this post the user defines their own macro and asks why one invocation works and the other doesn't. I am using a library and not my own macro.
This question is asking about why a macro expands differently in unicode mode versus ascii mode. I am not dealing with unicode so it is not relevant.
I am not using C++, only C which does not have syntax for generics, so this question does not apply to me.
Since I am not using XCode this question does not solve my problem.
I understand how macro expansion is supposed to work, so this question does tell me anything I don't already know.
I am not defining any new macros and do not have and problems with namespace collision, unlike this question.
In this and this question the user is not aware of the concatenation operator in macros. I am, and my problem is that it does not work the way I expect it too. So saying the operator exists does not help me.
This question is close to my problem, but it is occuring because an argument to a macro was not provided. I am providing all arguments so it does not help me.
This question the user is using the pasting operator when they don't need to.. In my case the pasting operator is necessary.

Well, it was something dumb. Posting this in case anyone runs across this answer.
The problem is my include guard. It should be FOO_BAR_H since the name of the file is foo-bar.h. However, it is defined as FOO_BAR. When gobject generates the token "FOO_BAR" the pre-processor realizes that it is a macro that has already been defined, but in this case the definition is empty. Nevertheless, it replaces the macro with its definition.
The solution is just replacing "FOO_BAR" with "FOO_BAR_H" in the include guard.

Related

C header declaration for generics (macro)

I am unsure about where to write the declaration and the call of a macro that replaces the code with a function. I do not really know if I should write the macro to the .h or .c file.
Before reading some stuff on the best ways to create libraries, I was just putting all the code in a header file and including it on my main, i.e.
#ifndef LIB
#define LIB
#define def_func(type) \
type func(type x) \
{ \
// Do something
}
func(int)
#endif
Some other functions use these defined functions so I had to call the macro to the .h file.
Firstly, I think that a few small edits are needed in the code from the question:
#ifndef LIB
#define LIB
#define def_func(type) \
type func(type x) \
{ \
/* Do something */ \
}
def_func(int)
#endif
The question does not detail what objective is being achieved, but I would assume that the goal is to create something that behaves like a template in C++, where the code is defined in one place and instances are created for different types by using the macro def_func.
One thing to be aware of is if you are using def_func more than once in your project, then you are going to have linker errors due to the same global symbol being used in multiple places, even if def_func is used in separate files. This could be avoided by making the function static if def_func is used multiple times but never more than once in the same file. Although, this would restrict the function from being called from multiple files.
Global symbol redefinition could also be avoided by adding another argument to the #define as follows:
#define def_func(func, type) \
type func(type x) \
{ \
/* Do something */ \
}
This would allow the function identifier to be specified uniquely. For example:
def_func(func_int, int)
would expand to:
int func_int(int x)
{
/* Do something */
}
This way a unique identifier would be created for each instance.
The #define should be placed in the header file if you intend to use the macro from multiple C source files. The macro should be used within C source files only, since using this in the header file would instantiate an object with the same global symbol in each case the header file is included. Although, this would be allowable if the functions are defined as static.
Lastly, if you plan to call the function created from multiple locations, you will need a macro that can be used in a header file associated with the module defining the function to prototype the function. For example:
#define def_func_proto(func, type) \
type func(type x)
So to sum it up, your library .h file would contain:
#define def_func(func, type) \
type func(type x) \
{ \
/* Do something */ \
}
#define def_func_proto(func, type) \
type func(type x)
Then using the integer case as an example, the C source file may include:
def_func(func_int, int)
Which would expand to (note that the actual expansion will not have line breaks):
int func_int(int x)
{
/* Do something */
}
In this case, the header file may contain:
def_func_proto(func_int, int);
Which would expand to:
int func_int(int x);
Finally, I would note that am not certain that this is a good programming practice, in general. You will want to be very cautious in implementing this in your program.

Multiple definition of function in the same place

I am trying to simulate generics in C by having some preprocessor definitions for a matrix type. Here is an excerpt of that:
#define __matrix_struct(TYPE) \
struct { \
uint32_t sz; \
TYPE **ptr; \
}
#define __matrix_t(TYPE) matrix_ ## TYPE
#define __matrix_ptr_t(TYPE) __matrix_t(TYPE) *
#define __matrix_typedef(TYPE) typedef __matrix_struct(TYPE) __matrix_t(TYPE)
#define __matrix_allocator_name(TYPE) TYPE ## _matrix_alloc
#define __matrix_allocator(TYPE) \
__matrix_ptr_t(TYPE) __matrix_allocator_name(TYPE) (uint32_t sz) { \
uint32_t i; \
__matrix_ptr_t(TYPE) m = (__matrix_ptr_t(TYPE)) malloc(sizeof(__matrix_t(TYPE))); \
m->ptr = (TYPE **) malloc(sz * sizeof(TYPE *)); \
for (i = 0; i < sz; ++i) { \
m->ptr[i] = (TYPE *) calloc(sz, sizeof(TYPE)); \
} \
return m; \
}
#define __matrix_deallocator_name(TYPE) TYPE ## _matrix_free
#define __matrix_deallocator(TYPE) \
void __matrix_deallocator_name(TYPE) (__matrix_ptr_t(TYPE) m) { \
uint32_t i; \
for (i = 0; i < m->sz; i++) { \
free(m->ptr[i]); \
} \
free(m->ptr); \
free(m); \
}
#define matrix_alloc_ptr(TYPE, SIZE) __matrix_allocator_name(TYPE) (SIZE)
#define matrix_dealloc_ptr(TYPE, PTR_NAME) __matrix_deallocator_name(TYPE) (PTR_NAME)
In another file, byte_matrix.h, I am trying to define a matrix of uint8_t values, as follows:
#include "matrix.h"
typedef uint8_t byte;
__matrix_typedef(byte);
__matrix_allocator(byte)
__matrix_deallocator(byte)
When I try to compile, I get the following errors:
CMakeFiles/tictac.dir/game/board.c.o: In function `byte_matrix_alloc':
/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:13: multiple definition of `byte_matrix_alloc'
CMakeFiles/tictac.dir/main.c.o:/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:13: first defined here
CMakeFiles/tictac.dir/game/board.c.o: In function `byte_matrix_free':
/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:14: multiple definition of `byte_matrix_free'
CMakeFiles/tictac.dir/main.c.o:/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:14: first defined here
I cannot understand why it would point to times to the same line and complain about that definition, since every header I wrote has include guards. Could you please explain this to me? Also if you know of a better approach to my problem, please let me know. Thanks.
Also I need to compile with -std=c99 if that matters in this case.
A quick fix would be to add static to your function definitions. This will create a static copy of these functions in each compilation unit which references the header. If you want the functions to be inlined every time, this is the way to go.
An alternative way to do it would be to keep function declarations in a .h file, and actual definitions in a single .c file. This approach will avoid duplication, and the compiler will not inline them (unless your linker supports link time optimization).
The reason is that you are including this header file in multiple compilation units. After the preprocessor does all the textual replacements, you end up with actual separate function definitions inside your .c files. And if you don't specify that you want them to be static, they are by default extern, which means that now the compiler doesn't know how to differentiate them if some other part of the code wants to call them.
This is what you basically do whenever you create a header file: you create a list of declarations which will be included in many compilation units, but there is always a single extern definition in a single .c file.
Another way (relative to the proposed by Groo) is to create two macros.
__matrix_allocator_declare with just prototype of function -- for h-file(s)
__matrix_allocator_define with function body -- for one (selected by you) c-file
This way requires to handle two macros and to not forget add function-body macro in some file, but (and it is more important for embedded applications on small microcontrollers) it guarantees that only one function instance will consume memory.

Eclipse CDT syntax error for macro using _Generic keyword

I'm using Oxygen with CDT 9.3.0 built-in.
When I use a macro I defined that uses _Generic, all those macro uses are underlined with "syntax error", but the project compiles fine (which is setup to use my makefiles).
After reading a similar so question, and since _Generic begin from C11 possibly not supported by eclipse's code analysis, I tried defining a symbol for my macro definition to empty but it didn't work. (At project settings, C/C++ General->Paths and Symbols->Symbols Tab, GNU C, added symbol CONVERT(...) without a value and added a symbol CONVERT(X), and CONVERT() and CONVERT without a value).
For example my macro is:
#define FIRST_(_1, ...) _1
#define FIRST(...) FIRST_(__VA_ARGS__, _1, _2, _3)
#define CONVERT(...) \
_Generic((FIRST(__VA_ARGS__)), \
char* : toText, \
int : toInt, \
) (__VA_ARGS__)
and usage point, that gives the syntax error:
void* test = CONVERT("testme");
As #ErikW pointed out, _Generic is a C11 feature that Eclipse CDT's parser does not support yet. This bug tracks adding support for it.
(By the way, contributions to Eclipse CDT's C11 support are very welcome!)
It is possible to work around this using macros.
The problem with trying to define another version of the CONVERT(...) macro in "Paths and Symbols" is that the macros defined there are treated as if you wrote them at the very top of your file. A subsequent redefinition in your actual code overwrites the definition from "Paths and Symbols".
I can think of two approaches to go about this:
Approach 1
CDT defines a special macro __CDT_PARSER__ which evaluates to true when it's parsing the code, but false when the code is actually compiled.
You can take advantage of this to define a different version of CONVERT(...) for CDT's purposes:
#ifdef __CDT_PARSER__
#define CONVERT(...)
#else
#define CONVERT(...) \
_Generic((FIRST(__VA_ARGS__)), \
char* : toText, \
int : toInt, \
) (__VA_ARGS__)
#endif
This almost works, but not quite. We still get a syntax error, because this line:
void* test = CONVERT("testme", 42);
will now expand to:
void* test = ;
As you can see, we don't actually want an empty expansion for CONVERT(...). We want an expansion that will parse as a variable's initializer. 0 will work:
#ifdef __CDT_PARSER__
#define CONVERT(...) 0
#else
...
#endif
Approach 2
Instead of defining a different version of CONVERT(...), we could define _Generic(...) itself to be a macro for CDT's purposes.
This time, we can do it in "Paths and Symbols", because there is no redefinition of _Generic(...) in the code that would mess it up.
So let's define a symbol in "Paths and Symbols", with _Generic(...) as the name and an empty value.
Now, this line:
void* test = CONVERT("testme", 42);
will expand to:
void* test = _Generic((FIRST("testme", 42)), \
char* : toText, \
int : toInt, \
) ("testme", 42)
which will in turn expand to:
void* test = ("testme", 42);
which parses (("testme", 42) parses as a parenthesized comma-expression and is thus a valid initializer).
This approach has the advantage that you don't need to modify your actual code, and that it handles all uses of the _Generic macro rather than just the one in CONVERT.
On the other hand, it's possible that for some other uses of the _Generic macro, this particular expansion won't parse. If that's the case, you might be able to come up with a different expansion that will parse for all uses, or else you can go with Approach 1.

GCC __func__ gets evaluated to an empty string

Given the following code in a project I'm working on:
/* Pre-definitions in a pre-definitions file to be included in the project */
#ifdef WIN32
#define __FUNCNAME__ __FUNCTION__
#else
#define __FUNCNAME__ __func__
#endif
/* My definitions */
#define MAC() \
MAC1()
#define MAC1() \
myPrintFunction(__FUNCNAME__)
/* My print function */
void myPrintFunction(const char * functionName)
{
printf("\n func name: %s \n",functionName);
}
/* Macro usage example function */
void myFunction()
{
if (some_condition)
{
MAC();
}
}
The function name is presented as an empty string.
Any idea why, and how can I fix it?
Code compiled and tested on Linux machine, using GCC compiler.
Use __func__ out of the box. It's been part of the C standard since C99. Change your compiler settings to use at least that standard.
Note that __func__ is not a macro but a predefined identifier which takes the form such that writing it anywhere within a function body is exactly equivalent to using it at that point, having first written
static const char __func__[] = "function-name";
just after the opening brace of a function body.
Formally the behaviour of your current code is undefined. Any symbol containing two consecutive underscores is reserved by the system. (That includes macro names, function names, and variable names.)
Your code as presented gives the expected result (once I'd added the necessary includes and main):
#include <stdio.h>
#ifdef WIN32
#define __FUNCNAME__ __FUNCTION__
#else
#define __FUNCNAME__ __func__
#endif
/* My definitions */
#define MAC() \
MAC1()
#define MAC1() \
myPrintFunction(__FUNCNAME__)
void myPrintFunction(const char * functionName)
{
printf("\n func name: %s \n",functionName);
}
int main()
{
MAC();
}
I compiled this using gcc -std=c11 -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds with no warnings.
You should really post a complete (but minimal) example that actually compiles, along with the compiler flags you used, as something must certainly be different to explain the symptoms you describe.
Also, when writing statements as macros, you may find it helpful to use the do {...} while (0) idiom to avoid unexpected expansions changing the control flow.

Can macros be used to simulate C++ templated functions?

I have a C program in which I need to create a whole family of functions which have the same signatures and bodies, and differ only in their types. What I would like to do is define a macro which generates all of those functions for me, as otherwise I will spend a long time copying and modifying the original functions. As an example, one of the functions I need to generate looks like this:
int copy_key__sint_(void *key, void **args, int argc, void **out {
if ((*out = malloc(sizeof(int))) {
return 1;
}
**((_int_ **) out) = *((_int_ *) key);
return 0;
}
The idea is that I could call a macro, GENERATE_FUNCTIONS("int", "sint") or something like this, and have it generate this function. The italicized parts are what need to be plugged in.
Is this possible?
I don't understand the example function that you are giving very well, but using macros for the task is relatively easy. Just you wouldn't give strings to the macro as arguments but tokens:
#define DECLARE_MY_COPY_FUNCTION(TYPE, SUFFIX) \
int copy_function_ ## SUFFIX(unsigned count, TYPE* arg)
#define DEFINE_MY_COPY_FUNCTION(TYPE, SUFFIX) \
int copy_function_ ## SUFFIX(unsigned count, TYPE* arg) { \
/* do something with TYPE */ \
return whatever; \
}
You may then use this to declare the functions in a header file
DECLARE_MY_COPY_FUNCTION(unsigned, toto);
DECLARE_MY_COPY_FUNCTION(double, hui);
and define them in a .c file:
DEFINE_MY_COPY_FUNCTION(unsigned, toto);
DEFINE_MY_COPY_FUNCTION(double, hui);
In this version as stated here you might get warnings on superfluous `;'. But you can get rid of them by adding dummy declarations in the macros like this
#define DEFINE_MY_COPY_FUNCTION(TYPE, SUFFIX) \
int copy_function_ ## SUFFIX(unsigned count, TYPE* arg) { \
/* do something with TYPE */ \
return whatever; \
} \
enum { dummy_enum_for_copy_function_ ## SUFFIX }
Try something like this (I just tested the compilation, but not the result in an executed program):
#include "memory.h"
#define COPY_KEY(type, name) \
type name(void *key, void **args, int argc, void **out) { \
if (*out = malloc(sizeof(type))) { \
return 1; \
} \
**((type **) out) = *((type *) key); \
return 0; \
} \
COPY_KEY(int, copy_key_sint)
For more on the subject of generic programming in C, read this blog wich contains a few examples and also this book which contains interesting solutions to the problem for basic data structures and algorithm.
That should work. To create copy_key_sint, use copy_key_ ## sint.
If you can't get this to work with CPP, then write a small C program which generates a C source file.
Wouldn't a macro which just takes sizeof(*key) and calls a single function that uses memcpy be a lot cleaner (less preprocessor abuse and code bloat) than making a new function for each type just so it can do a native assignment rather than memcpy?
My view is that the whole problem is your attempt to apply C++ thinking to C. C has memcpy for a very good reason.

Resources