- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
// Компилировать: g++ -o test reghead.cpp object1.cpp regtail.cpp main.cpp
//================== object.h: ==================
struct Object {
const char *name;
unsigned char props[0];
};
extern Object *head, *tail;
enum {PROPTYPE_BYTE = 0x40, PROPTYPE_WORD = 0x80};
enum {PROP_DESC = 1, PROP_LASTSTRING, PROP_COLOR, PROP_MASS, PROP_END = 0};
#define DECLARE_OBJECT(name) \
extern Object Object_##name, *name##_reg; \
Object *name##_reg __attribute__((section("oreg"))) = &Object_##name;\
Object Object_##name = {#name}; \
namespace name##_props {
#define PROP_BYTE(id, value) unsigned char id##_1 = id | PROPTYPE_BYTE, id##_2 = value;
#define PROP_WORD(id, value) unsigned char id##_1 = id | PROPTYPE_WORD, id##_2[2] = {value & 0xff, value >> 8};
#define PROP_STRING(id, value) unsigned char id##_1 = id; unsigned char id##_2[] = value;
#define END_PROPS unsigned char final = PROP_END; }
//================== reghead.cpp: ==================
#include "object.h"
Object *head __attribute__((section("oreg"))) = 0;
//================== regtail.cpp: ==================
#include "object.h"
Object *tail __attribute__((section("oreg"))) = 0;
//================== object1.cpp: ==================
#include "object.h"
DECLARE_OBJECT(object1)
PROP_BYTE(PROP_COLOR, 14)
PROP_WORD(PROP_MASS, 300)
PROP_STRING(PROP_DESC, "description")
END_PROPS
//================== main.cpp: ==================
#include <stdio.h>
#include <string.h>
#include "object.h"
int main()
{
Object **obj = &head;
while (++obj <= &tail) {
if (*obj == NULL)
continue;
printf("Object: %s\n", (*obj)->name);
unsigned char *props = (*obj)->props;
int id;
while ((id = *props) != PROP_END) {
if (id < PROP_LASTSTRING) {
char *value = (char *)props+1;
props = (unsigned char *)value + strlen(value) + 1;
switch (id) {
case PROP_DESC:
printf(" Description: %s\n", value);
break;
}
} else {
int value;
switch (id >> 6) {
case 1:
value = *((unsigned char *)(props+1));
props += 2;
break;
case 2:
value = *((unsigned short *)(props+1));
props += 3;
break;
}
switch (id & 63) {
case PROP_COLOR:
printf(" Color: %d\n", value);
break;
case PROP_MASS:
printf(" Mass:%d\n", value);
break;
}
}
}
}
}
Прошу прощения за длинный пример, но не мог не поделиться. Написано по мотивом кода из того же ZDaemon – примерно так там задаются и обрабатываются свойства объектов. Работает только с компилятором GCC. Если вы поняли, как это работает, а также почему подобный говнокод работает с gcc версии 3.2 и может зависать с более поздними версиями – можете по праву гордиться собой.
guest 13.02.2010 19:54 # 0
От компилятора зависит из-за этого
__attribute__((section("oreg")))
?
Arseniy 13.02.2010 20:26 # +3
> __attribute__((section("oreg")))
То, что это работает только с GCC – от этого. Что касается зависимости от версии – этот код рассчитывает на то, что инициализированные глобальные переменные располагаются в памяти подряд в порядке объявления, так вот есть подозрение, что в более новых GCC это бывает не так.
Основная задача примерно такая: имеется множество объектов, каждый из которых обладает набором свойств разных типов. Надо всё это описать на C++, причём каждый объект в отдельном файле, а потом пройтись по всем объектам и по всем свойствам каждого объекта.
Это делается так: описание объекта – экземпляр структуры Object, инициализированная глобальная переменная (строка 16). Сами же свойства (каждое из которых характеризуется типом – байт, слово или строка, идентифиактором – что за свойство и значением) хранятся в массиве из байт. Массив, по замыслу, находится в памяти сразу за экземпляром структуры. Формируется он путем объявления множества инициализированных глобальных переменных типа unsiged char или char []. Описание свойства: первый байт – старшие два бита отвечают за тип, остальные за идентификатор (0 означает конец списка); дальше – значение.
Чтобы пройтись по всем объектам, для каждого из них дополнительно объявляется глобальная переменная, инициализированная указателем на экземпляр структуры (строка 15). Причём они все помещаеются в отдельный сегмент данных (то самое __attribute__). Кроме того, в файлах reghead.cpp и regtail.cpp объявляются еще два указателя в том же сегменте. Значения всех этих указателей будут располагаться в памяти подряд (возможно, с заполненными нулями промежутками, учтенными в строках 50-51). Причём, если при сборке скармливать компилятору файлы именно в таком порядке, как указано (!!!), то значение указателя head будет располагаться в памяти перед всеми остальными, а tail – после всех остальных.
guest 13.02.2010 20:47 # 0
guest 20.02.2010 16:27 # 0
GNU ld вроде как бы от балды менять объекты местами не будет...
а как data driven система определения объектов может даже и работать, если например object1.cpp генерируется динамически из какой базы/etc.
ISith 15.02.2010 15:41 # 0
guest 15.02.2010 23:14 # 0
PS // это С99
PSS А namespace это #define namespace
ISith 16.02.2010 11:33 # 0
Те этого мало?? Да если "с дефайнами", то на половину говнокодов из питона, руби, сишарпа, делфи и т.д. можно говорить, что это си с препроцессором.
guest 16.02.2010 19:20 # 0
guest 20.02.2010 16:32 # 0
код - прямой с99 с GNU расширениями.
насколько долго код использует POD (plain old data), C++ не тригирется вообще.
разница будет только на бинарном уровне и тривиальная: mangled имена и код для обработки эксепшенов.
guest 20.02.2010 17:11 # 0
xaionaro 28.02.2010 17:37 # +0.2
2.) Файлы *.cpp (вы удивитесь, но "gcc *.cpp" скорее всего выдаст ошибку) и компилятор g++.
3.) И самый главный аргумент, что, млять, если бы автор закинул бы код в раздел "Си", то автора опять обкладывали бы всякие анонимусы, ибо очевидно, что код C++. Т.е. в данной ситуации как ни крути, анонимусы вроде вас будут возмущаться.