Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions navit/plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@

#include "plugin.h"
#include "config.h"
#include "debug.h"
#include "file.h"
#include "item.h"
#include "plugin_impl.h"
#include <glib.h>
#include <string.h>
#define PLUGIN_C
#include "debug.h"
#include "item.h"
#include "plugin.h"
#ifdef USE_PLUGINS
# ifdef HAVE_GMODULE
# include <gmodule.h>
Expand Down
92 changes: 21 additions & 71 deletions navit/plugin.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Navit, a modular navigation system.
* Copyright (C) 2005-2008 Navit Team
* Copyright (C) 2005-2026 Navit Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
Expand All @@ -17,11 +17,12 @@
* Boston, MA 02110-1301, USA.
*/

#ifndef PLUGIN_C
#ifndef NAVIT_PLUGIN_H
#define NAVIT_PLUGIN_H

# ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
# endif
#endif

struct plugin;

Expand Down Expand Up @@ -54,7 +55,6 @@ enum plugin_category {
/** Dummy for last entry. */
plugin_category_last,
};
#endif

struct container;
struct popup;
Expand All @@ -65,75 +65,23 @@ struct popup_item;
#undef PLUGIN_CATEGORY
#define PLUGIN_PROTO(name, ...) void name(__VA_ARGS__)

#ifdef PLUGIN_C
# define PLUGIN_REGISTER(name, ...) \
void plugin_register_##name(PLUGIN_PROTO((*func), __VA_ARGS__)) { \
plugin_##name##_func = func; \
}

# define PLUGIN_CALL(name, ...) \
{ \
if (plugin_##name##_func) \
(*plugin_##name##_func)(__VA_ARGS__); \
}
#define PLUGIN_FUNC1(name, t1, p1) \
void plugin_register_##name(void (*func)(t1 p1)); \
void plugin_call_##name(t1 p1);

# define PLUGIN_FUNC1(name, t1, p1) \
PLUGIN_PROTO((*plugin_##name##_func), t1 p1); \
void plugin_call_##name(t1 p1) PLUGIN_CALL(name, p1) PLUGIN_REGISTER(name, t1 p1)

# define PLUGIN_FUNC3(name, t1, p1, t2, p2, t3, p3) \
PLUGIN_PROTO((*plugin_##name##_func), t1 p1, t2 p2, t3 p3); \
void plugin_call_##name(t1 p1, t2 p2, t3 p3) PLUGIN_CALL(name, p1, p2, p3) \
PLUGIN_REGISTER(name, t1 p1, t2 p2, t3 p3)

# define PLUGIN_FUNC4(name, t1, p1, t2, p2, t3, p3, t4, p4) \
PLUGIN_PROTO((*plugin_##name##_func), t1 p1, t2 p2, t3 p3, t4 p4); \
void plugin_call_##name(t1 p1, t2 p2, t3 p3, t4 p4) PLUGIN_CALL(name, p1, p2, p3, p4) \
PLUGIN_REGISTER(name, t1 p1, t2 p2, t3 p3, t4 p4)

struct name_val {
char *name;
void *val;
};
#define PLUGIN_FUNC3(name, t1, p1, t2, p2, t3, p3) \
void plugin_register_##name(void (*func)(t1 p1, t2 p2, t3 p3)); \
void plugin_call_##name(t1 p1, t2 p2, t3 p3);

GList *plugin_categories[plugin_category_last];
#define PLUGIN_FUNC4(name, t1, p1, t2, p2, t3, p3, t4, p4) \
void plugin_register_##name(void (*func)(t1 p1, t2 p2, t3 p3, t4 p4)); \
void plugin_call_##name(t1 p1, t2 p2, t3 p3, t4 p4);

# define PLUGIN_CATEGORY(category, newargs) \
struct category##_priv; \
struct category##_methods; \
void plugin_register_category_##category(const char *name, struct category##_priv *(*new_)newargs) { \
struct name_val *nv; \
nv = g_new(struct name_val, 1); \
nv->name = g_strdup(name); \
nv->val = new_; \
plugin_categories[plugin_category_##category] = \
g_list_append(plugin_categories[plugin_category_##category], nv); \
} \
\
void *plugin_get_category_##category(const char *name) { \
return plugin_get_category(plugin_category_##category, #category, name); \
}

#else
# define PLUGIN_FUNC1(name, t1, p1) \
void plugin_register_##name(void (*func)(t1 p1)); \
void plugin_call_##name(t1 p1);

# define PLUGIN_FUNC3(name, t1, p1, t2, p2, t3, p3) \
void plugin_register_##name(void (*func)(t1 p1, t2 p2, t3 p3)); \
void plugin_call_##name(t1 p1, t2 p2, t3 p3);

# define PLUGIN_FUNC4(name, t1, p1, t2, p2, t3, p3, t4, p4) \
void plugin_register_##name(void (*func)(t1 p1, t2 p2, t3 p3, t4 p4)); \
void plugin_call_##name(t1 p1, t2 p2, t3 p3, t4 p4);

# define PLUGIN_CATEGORY(category, newargs) \
struct category##_priv; \
struct category##_methods; \
void plugin_register_category_##category(const char *name, struct category##_priv *(*new_)newargs); \
void *plugin_get_category_##category(const char *name);

#endif
#define PLUGIN_CATEGORY(category, newargs) \
struct category##_priv; \
struct category##_methods; \
void plugin_register_category_##category(const char *name, struct category##_priv *(*new_)newargs); \
void *plugin_get_category_##category(const char *name);

#include "plugin_def.h"

Expand Down Expand Up @@ -166,3 +114,5 @@ void *plugin_get_category(enum plugin_category category, const char *category_na
#ifdef __cplusplus
}
#endif

#endif /* NAVIT_PLUGIN_H */
90 changes: 90 additions & 0 deletions navit/plugin_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
* Navit, a modular navigation system.
* Copyright (C) 2005-2026 Navit Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/

/**
* @file plugin_impl.h
* @brief Plugin implementation macros — included only by plugin.c.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It its only included inside plugin.c why do we need a header for it?

@pgrandin pgrandin Mar 19, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It felt cleaner that way, keeping the .c file focused on the actual logic instead of dealing with macros. The impl header also needs to #undef and redefine several macros before re-expanding plugin_def.h a second time so that's ~60 lines of macro machinery that could clutter plugin.c if inlined.

What do you think?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, having it is fine and for my taste plugin.c still contains too many macros/defines (which is no way speaking to this PR but rather to the structure that is in place).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did notice there is still some kind of problem around plugin_def.h. If that one receives an include guard, linking fails. I have not been able to look into this further

*
* This header provides the macro definitions that expand PLUGIN_FUNC* and
* PLUGIN_CATEGORY into function bodies and global variable definitions.
* It must be included exactly once, after plugin.h, in plugin.c.
*/

#ifndef NAVIT_PLUGIN_IMPL_H
#define NAVIT_PLUGIN_IMPL_H

#include "plugin.h"
#include <glib.h>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think including "glib.h" is better here, if we want to continue supporting platforms without native glib.


#undef PLUGIN_FUNC1
#undef PLUGIN_FUNC3
#undef PLUGIN_FUNC4
#undef PLUGIN_CATEGORY

#define PLUGIN_REGISTER(name, ...) \
void plugin_register_##name(PLUGIN_PROTO((*func), __VA_ARGS__)) { \
plugin_##name##_func = func; \
}

#define PLUGIN_CALL(name, ...) \
{ \
if (plugin_##name##_func) \
(*plugin_##name##_func)(__VA_ARGS__); \
}

#define PLUGIN_FUNC1(name, t1, p1) \
PLUGIN_PROTO((*plugin_##name##_func), t1 p1); \
void plugin_call_##name(t1 p1) PLUGIN_CALL(name, p1) PLUGIN_REGISTER(name, t1 p1)

#define PLUGIN_FUNC3(name, t1, p1, t2, p2, t3, p3) \
PLUGIN_PROTO((*plugin_##name##_func), t1 p1, t2 p2, t3 p3); \
void plugin_call_##name(t1 p1, t2 p2, t3 p3) PLUGIN_CALL(name, p1, p2, p3) \
PLUGIN_REGISTER(name, t1 p1, t2 p2, t3 p3)

#define PLUGIN_FUNC4(name, t1, p1, t2, p2, t3, p3, t4, p4) \
PLUGIN_PROTO((*plugin_##name##_func), t1 p1, t2 p2, t3 p3, t4 p4); \
void plugin_call_##name(t1 p1, t2 p2, t3 p3, t4 p4) PLUGIN_CALL(name, p1, p2, p3, p4) \
PLUGIN_REGISTER(name, t1 p1, t2 p2, t3 p3, t4 p4)

struct name_val {
char *name;
void *val;
};

GList *plugin_categories[plugin_category_last];

#define PLUGIN_CATEGORY(category, newargs) \
struct category##_priv; \
struct category##_methods; \
void plugin_register_category_##category(const char *name, struct category##_priv *(*new_)newargs) { \
struct name_val *nv; \
nv = g_new(struct name_val, 1); \
nv->name = g_strdup(name); \
nv->val = new_; \
plugin_categories[plugin_category_##category] = \
g_list_append(plugin_categories[plugin_category_##category], nv); \
} \
\
void *plugin_get_category_##category(const char *name) { \
return plugin_get_category(plugin_category_##category, #category, name); \
}

#include "plugin_def.h"

#endif /* NAVIT_PLUGIN_IMPL_H */
Loading