коллега подобное делал для ретаргетинга printf-а (GCC в EmBitz) завел несколько таких структур
typedef struct IODEV{
int (*write)(void* msg, int len);
int (*putchar)(int c);
int (*getchar)(void);
int (*read)(void* msg, int len);
int (*ioctl)(unsigned int fun, unsigned long param);
}IODEV;
/// Implemented in user code
extern const struct IODEV* iodevs_stdio[];
extern int iodevs_stdio_count;
extern const struct IODEV* iodevs_stream[];
extern int iodevs_stream_count;
одна из
const IODEV IODEV_ITM={
.write = ITM_write,
.getchar = ITM_getchar,
.putchar = ITM_putchar,
.read = ITM_read,
};
сложил указатели на них
const IODEV* iodevs_stdio[]={
&IODEV_ITM,
&IODEV_ITM,
&IODEV_ITM,
};
const IODEV* iodevs_stream[]={
&IODEV_ITM,
};
зацепил в иниты
/// Implemented in user code
extern const struct IODEV* iodevs_stdio[];
extern int iodevs_stdio_count;
extern const struct IODEV* iodevs_stream[];
extern int iodevs_stream_count;
#include <stdio.h>
void IODEV_set_stdio(const IODEV* d){
setbuf(stdin, NULL);
setbuf(stdout, NULL);
stdout->_flags = __SWR | __SSTR;
iodevs_stdio[0] = d;
iodevs_stdio[1] = d;
}
void IODEV_set_stderr(const IODEV* d){
setbuf(stderr, NULL);
iodevs_stdio[2] = d;
}
соответственно в той же _write выбирается откуда что взять
static int _write(int file, char *ptr, int len) {
IODEV* d = _select_dev(file);
if(d) return(d->write(ptr, len));
return len; //as to null device
}
сама выбиралка гребётся по подготовленными массивам указателей на структуры
static IODEV* _select_dev(int d) {
if(IODEV_MAJOR(d)==IODEV_MAJOR_STDIO){
d = IODEV_MINOR(d);
if(d < iodevs_stdio_count) return((IODEV*)*(iodevs_stdio+d));
} else if(IODEV_MAJOR(d)==IODEV_MAJOR_STREAM){
d = IODEV_MINOR(d);
if(d<iodevs_stdio_count) return((IODEV*)*(iodevs_stream+d));
}
errno = EBADF; return(NULL);
}
в общем как-то так. по дефолту заряжается вывод в stderr через SWO (ITM).
лично меня от этой мути тошнит слегка:)