I have a problem. I'm trying to add struct elements by previously defined constant.
This is sample code (OpenGL+WinAPI)
#define ENGINE_STRUCT \
HGLRC RenderingContext;\
HDC DeviceContext;
And then:
typedef struct SWINDOW {
ENGINE_STRUCT
HWND Handle;
HINSTANCE Instance;
CHAR* ClassName;
BOOL Fullscreen;
BOOL Active;
MSG Message;
} WINDOW;
Is this possible?
Yes it is possible, a macro is a simple textual substitution
http://www.cplusplus.com/doc/tutorial/preprocessor/
The preprocessor examines the code before actual compilation of code
begins and resolves all these directives before any code is actually
generated by regular statements.
Related
I have created a macro for initializing a structure with some data, including a callback function pointer because this code is extensively reused in my file. I am storing the function pointer so I can simply iterate over the structure without having to explicitly check the msg_id and call the corresponding handling function.
These lines of code are around line number 150 :
typedef struct my_struct {
some_list *child_list;
void *data;
void *msg_func;
int nesting_level;
int msg_id;
} my_struct_t;
#define MALLOC_STRUCT_WITH_BASIC_DATA(level, msg_id, data_arg) \
my_struct_t *new_child = NULL; \
MY_CALLOC(new_child, my_struct_t, 1, failure); \
LISTCREATE(new_child->child_list); \
new_child->data = data_arg; \
#define INIT_MY_STRUCT(level, msg_id, data_arg, child_func) \
if (some_condition_on_data_arg_is_satisfied(data_arg)) { \
MALLOC_STRUCT_WITH_BASIC_DATA(level, msg_id); \
new_child->msg_func = &child_func; \
(new_child->msg_func)(new_child, new_child->data); \
}
There are about 100+ msg functions and the list will keep increasing in the future. Their declarations are around line 250 :
static void msg_function1(my_struct_t *st, data_type1 *ptr_data);
static void msg_function2(my_struct_t *st, data_type2 *ptr_data);
...
static void msg_functionn(my_struct_t *st, data_typen *ptr_data);
Finally, the macros are invoked around line number 580 and message handling functions are defined starting around line number 700.
I get a compilation error when the macro is encountered :
my_file.c:586: error: called object ‘new_child->msg_func’ is not a function
This is my first time using function pointers. I searched on stackoverflow and google and tried to eliminate possible causes, including ordering of function declaration and usage. Could someone please help me understand what am I doing wrong here? To note, I do not have permission to change the message handling functions' type to void * or something else.
You need to have a function pointer not an "ordinary" void pointer in your structure.
typedef struct my_struct {
some_list *child_list;
void *data;
void (*msg_func)(my_struct_t *, void *);
int nesting_level;
int msg_id;
} my_struct_t;
Ten message functions should convert the void pointer to the correct object pointer
static void msg_function2(my_struct_t *st, void *vData)
{
data_type2 *ptr_data = vData;
/* ... */
I'm writing a C program using the Windows API. Each major function has its own file, and there is one header for the prototypes and includes and whatnot:
// Headers & global constants
#pragma once
#define _WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <WindowsX.h>
#include <Windef.h>
#define szClassName TEXT("EthicsPresentationWnd")
// Prototypes
LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK FontProc1(HWND hWnd, LPARAM lParam);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd);
ATOM RegisterWindow(HINSTANCE hInstance);
The thing I'm irritated about is the #define szClassName line. I dislike using macros and would prefer to have a proper global variable, wchar_t szClassName[], but if I do that then the linker complains about multiply defined variables in each of the modules that include the header.
I thought the #pragma once directive would prevent this, but it didn't.
Is there any solution to this problem?
The solution to this is to have a separate declaration and definition...
Header (*.h; sorry, I don't know WinAPI type names, adapt as necessary):
extern const char szClassName[];
Implementation (*.c or *.cpp)
const char szClassName[] = "hello, world"
You're seeing the problem because a new symbol szClassName is being declared each time one of your *.c or *.cpp files includes the header (even with the include guards!); and that makes the linker confused (see below).
Do note that this will make sizeof(szClassName) not work anymore.
Further explanation:
After preprocessing, the compiler is basically seeing this:
file "a.c": const char someSymbol[] = <some text, don't care what right now>;
file "b.c": const char someSymbol[] = <some text, don't care if it's the same>;
file "c.c": const char someSymbol[] = <some text, ditto>;
When the linker is linking the object files (say, "a.obj", "b.obj" and "c.obj"), it sees the same symbol being defined with a new value (at least as far as the linker is concerned) --- and thus it fails with an error.
Place it in between
#ifndef GLOB_CONST_H
#define GLOB_CONST_H
// All macro definitions
// and type definitions
#endif
Use extern keyword to declare your global variables and put those declarations in this header file. After that you need to place the definition of all the variables in a .c file.
You can declare the variable as static so that each module that includes the .h file gets its own local unique copy that the linker will not complain about, as each copy will have local linkage instead of external linkage. This also eliminates the need for declaring the variable as extern and defining it in a separate .c file.
static const TCHAR szClassName[] = TEXT("EthicsPresentationWnd");
Or;
static const TCHAR *szClassName = TEXT("EthicsPresentationWnd");
Or:
static LPCTSTR szClassName = TEXT("EthicsPresentationWnd");
Use header guards in all your header file and declare a global variable in .c file and declare extern to that global variable in a header file.
#ifndef HEADER_FILE_NAME_H /* if not defined already */
#define HEADER_FILE_NAME_H
extern wchar_t szClassName[];
#endif
In any one of your .c file define the global variable.
wchar_t szClassName[];
I have errors when compiling my project with codeblocks.
My problem comes from a enum definition, and from a struct definition.
They are bot defined in a header file, that worked since i was only using those enum and struct in the .c associated file. But when i include the .h file in another .c file, i get errors, here is some code;
maps.h
#include <stdlib.h>
#include <stdio.h>
enum Property { BACKGROUND, FOREGROUND, BLOCK, EVENT };
typedef struct {
char map_name[50];
int width;
int height;
char* map_struct;
}rpgMap;
char getTileProperty(rpgMap map, int x, int y, int property);
maps.c
#include "maps.h"
char getTileProperty(rpgMap map, int x, int y, int property){ // Works
char value = NULL;
value = map.map_struct[(((y*(map.width-1))+y+x) * 4 ) + property];
return value;
}
rpgMap loadMap(unsigned char* map){
rpgMap Map;
//....
//some code
//...
return Map;
}
// This works until i include maps.h in another .c file
So here's the stuff, when i include maps.h in eg. game.c or game.h i have this error;
error: nested redefinition of 'enum Property'
I don't get it !
You need to add header guards to your header files otherwise you will get multiple declarations.
For example, for your maps.h surround it with this:
#ifndef MAPS_H
#define MAPS_H
...
#endif
Any source file that includes your header file will declare a single instance variable with the possible enumerated values of { BACKGROUND, FOREGROUND, BLOCK, EVENT }. I'm not sure that this is your intention. In general it is not good practice to do so.
If you intended to declare a type of enumeration and allow instances to be created elsewhere, put this in your header file:
typedef enum { BACKGROUND, FOREGROUND, BLOCK, EVENT } Property_t;
And then in your source files, declare the enumeration like so:
static Property_t property = BACKGROUND;
If you intended to create a variable that can be accessed from multiple source files then do put this in your header file:
typedef enum { BACKGROUND, FOREGROUND, BLOCK, EVENT } Property_t;
extern Property_t property;
and in a single source file, declare the variable:
Property_t property = BACKGROUND;
I have a doubt about a syntax used in linux kernel code. I have an intuition of what it does but I want to know it more formally. I am using kernel v3.5.4
In file /include/linux/sched.h the following is defined
struct task_struct {
volatile long state;
//some more data members
};
and in file /include/linux/init_task.h file the following is defined:
#define INIT_TASK(tsk) {
.state = 0, \
//some more initializations
}
I am confused about two things:
a) I feel it is used for initialization but can anyone suggest some good read for this type of initialization for structures.
b) I do not understand how the following initialization works. Like how this #define and the corresponding task_struct structure are related.
[EDIT]
I noticed the following things also:
c) Is \ at the end of every line necessary.
d) There are many parts of kernel doe wrapped in #ifdef #endif. If you want to initialize a data member wrapped in #ifdef #endif can we use this form of initialization. I mean can we use #ifdef #endif inside INIT_TASK() like this
#define INIT_TASK(tsk) {
.state = 0, \
//some more initializations
#ifdef CX
.tickets = 5, \
#endif
}
struct task_struct whatever = INIT_TASK(someTsk);
This results in the following code:
struct task_struct whatever = { .state = 0 };
which is valid C syntax to initialize fields in a struct via their name instead of their position. Doing so makes the code safe against struct members that are not added at the last position.
Regarding the backslashes: Yes, they are necessary so the preprocessor knows that the macro continues on the next line.
No, you cannot use #ifdef inside a macro.
I'm writing this awesome application, at least I think it awesome, in C with the magnificent blend of GObject and after a while I start getting this very, extremely strange error. I also believe to have noticed it not appearing always. However this might just be the IDE's fault. Anyhow...
GCC, apparently, complains: expected ')' before '*' token; this happens in a header file.
This is that very same header file.
#pragma once
#include "global.h"
#include "CharcoalApp.h"
GtkListStore *WebsitesListStore;
// that error is reported for this line
void charcoal_websites_list_initialize(CharcoalApp *app);
As far as I can see, this comes from the CharcoalApp *app parameter for that function.
Because I cannot really understand why this error is happening, I'll include the CharcoalApp.h file. global.h is a very simple header file that carries the main dependencies, mainly GLib, GObject, GThread, GTK+, WebKit and other.
CharcoalApp.h
#ifndef __CHARCOAL_APP_H__
#define __CHARCOAL_APP_H__
#include "global.h"
#include "CharcoalDB.h"
#include "CharcoalWindow.h"
#include "CharcoalWebsitesList.h"
G_BEGIN_DECLS
#define CHARCOAL_TYPE_APP (charcoal_app_get_type())
#define CHARCOAL_APP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), CHARCOAL_TYPE_APP, CharcoalApp))
#define CHARCOAL_APP_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), CHARCOAL_TYPE_APP, CharcoalApp const))
#define CHARCOAL_APP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CHARCOAL_TYPE_APP, CharcoalAppClass))
#define CHARCOAL_IS_APP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), CHARCOAL_TYPE_APP))
#define CHARCOAL_IS_APP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), CHARCOAL_TYPE_APP))
#define CHARCOAL_APP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), CHARCOAL_TYPE_APP, CharcoalAppClass))
typedef struct _CharcoalApp CharcoalApp;
typedef struct _CharcoalAppClass CharcoalAppClass;
typedef struct _CharcoalAppPrivate CharcoalAppPrivate;
struct _CharcoalApp {
GObject parent;
CharcoalAppPrivate *priv;
GtkBuilder *ui;
CharcoalDB *db;
// toplevels
GtkWidget *CharcoalWindow;
};
struct _CharcoalAppClass {
GObjectClass parent_class;
};
GType charcoal_app_get_type(void) G_GNUC_CONST;
CharcoalApp *charcoal_app_new(void);
void charcoal_app_quit(CharcoalApp *app);
G_END_DECLS
#endif /* __CHARCOAL_APP_H__ */
Thank you for your help!
CharcoalApp is not declared in global.h. Suppose you are including CharcoalApp.h in your C file:
CharcoalApp.h is read up to #include "global.h"
global.h is included
Error: expected ')' before '*' token
You should rearrange your header files properly or use a forward declaration (although I don't think is needed in this case).
There are many solutions:
the proper way: include CharcoalApp.h from global.h, not the reverse;
move typedef struct _CharcoalApp CharcoalApp; before `#include "global.h" in CharcoalApp.h;
remove #include "global.h" from CharcoalApp.h and include them in the proper order (global.h last).
I'm not sure if it's obvious to everyone, but I should add that the reason it's complaining (I think) is because it doesn't understand that CharcoalApp is a type name at the time that it's parsing that code (I've seen similar compile-time errors many times in the past). I think it is handling it as a parameter name instead of a parameter's type name, so it expects the end of the argument list (or a comma) instead of another parameter name without a comma.
How about:
#pragma once
#include "global.h"
//#include "CharcoalApp.h"
struct CharcoalApp;
GtkListStore *WebsitesListStore;
// that error is reported for this line
void charcoal_websites_list_initialize(CharcoalApp *app);
Its not exactly pretty, but removing header includes inside other headers and replacing them with forward declarations is something I was taught once and always try to do.
It reduces the amount of time I spend swearing at the compiler over cyclic dependancy significantly, and it also keeps build times down when changing a commonly included header file.
: D
Looks to me like GtkListStore is not defined.
Try changing your code to:
struct _CharcoalApp {
GObject parent;
CharcoalAppPrivate *priv;
GtkBuilder *ui;
CharcoalDB *db;
// toplevels
GtkWidget *CharcoalWindow;
};
struct _CharcoalAppClass {
GObjectClass parent_class;
};
typedef struct _CharcoalApp CharcoalApp;
typedef struct _CharcoalAppClass CharcoalAppClass;
typedef struct _CharcoalAppPrivate CharcoalAppPrivate;
When you uttered the typedef, the underlying structure type wasn't defined yet, and this MIGHT have confused something.
I normally just write something like:
typedef struct {
GObject parent;
CharcoalAppPrivate *priv;
GtkBuilder *ui;
CharcoalDB *db;
// toplevels
GtkWidget *CharcoalWindow;
} CharcoalApp;