2016-11-09 23 views
0

我正在玩预处理器和c。试图实现我自己的事件和分级系统。 但是我面临一个问题。我试图静态定义可以初始化的“模块”,以及一些事件,这些事件也是事先静态定义的。对于我正在使用的活动COUNTER,它的作品很漂亮。但我不想混用模块ID和事件ID。多个__COUNTER__ C

所以我想要实现一个简化版本:

hierarchy.h

#define HIERARCHY_DEFINE(NAME) int hierarchyId = __COUNTER__ 

event.h

#define EVENT_REGISTER(NAME) int eventId = __COUNTER__ 

的main.c

#include "event.h" 
#include "hierarchy.h" 

EVENT_REGISTER(EventOne); 
HIERARCHY_DEFINE(ModuleOne); 
EVENT_REGISTER(EventTwo); 

int main(void){ 
    printf("events(%d, %d) modules(%d)\n",EventOne,EventTwo,ModuleOne); 
    return 1; 
} 

这将打印出:

events(0, 2) modules(1) 

当我试图实现:

events(0, 1) modules(0) 

我环顾四周,人们说我不能创建我自己的计数器。并看到了增强计数器,但是这并没有达到我想要的。

有没有人知道我该如何处理这种情况?

谢谢!

编辑:什么我的代码实际上看起来像

struct Event{ 
    uint8_t eventId; 
    uint8_t * data; 
    const char * description; 
}; 

#define EVENT_REGISTER(eventName, desc)\ 
static Event eventName = {.eventId = __COUNTER__, .data = 0, .description = desc } 




EVENT_REGISTER(Timer_5, "Timer 5 hZ"); 
+0

如果ID是静态定义的,它们可以进入'enum',对吧? –

+0

所以你想要一个事件计数器,一个模块,这两个计数器应该是分开的?那么为什么不使用两个变量,初始化为零并在宏中增加?例如。 'int eventId = eventIdCounter ++;' –

+0

他们可以,但是我喜欢尽可能简单地注册一个事件。现在只有一条线就足够了。不想一直添加或删除或更改事件时必须更改枚举 – Elamre

回答

1

您必须:在运行时

  • 分配ID,
  • 用手
  • 或保持在一个地方的所有事件和模块定义分配ID。

想想看,你有a.cb.c,它们分别包含了一些EventAEventB定义。由于它们是独立的编译单元,因此编译器无法为其分配不重叠的ID。编译b.c,它甚至不知道有另一个a.c其中编号1已被分配。

对于第一个,有一个RegisterEvent功能,像这样:

void RegisterEvent(Event* event){ 
    static int nextEventId = 0; 
    event->eventId = nextEventId; 
} 

,并调用它的每Event你的需要。

第二个是显而易见的,但繁琐和容易出错。

对于第三种解决方案,您可以使用X macro

拥有所有事件的X-列表:

#define EventList \ 
    Event(FirstEvent, "FirstEvent") \ 
    Event(Timer_1, "Timer 1 hZ") \ 
    ... 
    Event(Timer_5, "Timer 5 hZ") 

如今,在头部有你要声明所有的事件(比如,events.h):

#define Event(name, desc) EventID ## name, 
enum EventID{ 
EventIDZero = 0, 
EventList 
EventIDCount 
}; 
#undef Event 

#define Event(name, desc) \ 
    extern Event name; 
EventList 
#undef Event 

而且在一个单一的编译单元,您的事件定义将驻留(例如,events.c):

#include "events.h" 

#define Event(name, desc) \ 
    Event name = {.eventId = EventID ## name, .data = 0, .description = desc }; 
EventList 
#undef Event 

宏展开后,events.c样子(略加编辑,以便阅读):

enum EventID{ 
EventIDZero = 0, 
EventIDFirstEvent, EventIDTimer_1, EventIDTimer_5, 
EventIDCount 
}; 

extern Event FirstEvent; 
extern Event Timer_1; 
extern Event Timer_5; 

Event FirstEvent = {.eventId = EventIDFirstEvent, .data = 0, .description = "FirstEvent" }; 
Event Timer_1 = {.eventId = EventIDTimer_1, .data = 0, .description = "Timer 1 hZ" }; 
Event Timer_5 = {.eventId = EventIDTimer_5, .data = 0, .description = "Timer 5 hZ" }; 

同样的事情会的模块。

+0

感谢您的X宏!这就是我希望通过这样做发现的东西。尽管在这种情况下它可能不是最好的方法 – Elamre

3

除非你有一个标识符附加要求

轻微ADITION,下面会做什么:

definitions.inc

EVENT_REGISTER(Timer_5, "Timer 5 Hz") 
EVENT_REGISTER(Timer_10, "Timer 10 Hz") 
MODULE_REGISTER(Module_SSH) 
MODULE_REGISTER(Module_NCO) 
#undef EVENT_REGISTER 
#undef MODULE_REGISTER 

app.c

#define EVENT_REGISTER(a, d) a, 
#define MODULE_REGISTER(a) 
enum events { 
#include "definitions.inc" 
}; 

#define EVENT_REGISTER(a, d) 
#define MODULE_REGISTER(a) a, 
enum modules { 
#include "definitions.inc" 
}; 

struct Event { 
    uint8_t event_id; 
    uint8_t *data; 
    const char *description; 
}; 

#define MODULE_REGISTER(a) 
#define EVENT_REGISTER(a, d) static struct Event Event_##a = { .event_id = a, \ 
    .data = NULL, \ 
    .description = d \ 
}; 
#include "definitions.inc" 


int main (int argc, char **argv) 
{ 
    printf("events(%d, %d) modules(%d)\n", Timer_10, Timer_5, Module_SSH); 

    return EXIT_SUCCESS; 
} 
+0

这会工作,是的,但现在我需要维护在两个枚举列表中。 – Elamre

+0

你指的是什么样的保养? –

+0

那么,我将不得不在某个地方注册该事件,我将不得不将其添加到枚举中 – Elamre