[vlc-devel] RFC: type-punning between (future) vlc_frame_t and vlc_data_t
Thomas Guillem
thomas at gllm.fr
Fri Apr 26 09:47:37 CEST 2019
Question following my remark on the "[PATCH 00/17] RFC Split block_t into 2 different data containers" thread:
"- Code duplication between data.c and frame.c and also between data_helper.h and frame_helper.h: This code is far from trivial and should not be duplicated. We don't want to fix 2 files each time we need to fix a bug. The only way I see to solve this issue is to include vlc_data_t from vlc_frame_t and have generic vlc_data_t functions working with vlc_frame_t."
I wonder if it is possible to include vlc_data_t from vlc_frame_t without renaming all variables (in order to avoid a s/frame->p_buffer/frame->data.p_buffer/ change). Actually, it is possible in C by using anonymous unions and structs but is it allowed ?
cf. https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Type-punning
PS: ISO C++ prohibits anonymous structs so we will have to rename all C++ code that touch vlc_frame_t
Here is a sample to show what I would to do in VLC:
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <stdint.h>
#include <inttypes.h>
#define DATA_MEMBERS \
uint8_t *buf; \
size_t size; \
size_t maxsize; \
void *start; \
struct data {
DATA_MEMBERS
struct data *next;
};
struct frame
{
union
{
struct data d;
#ifndef __cplusplus
/* ISO C++ prohibits anonymous structs*/
struct {
DATA_MEMBERS
struct frame *next;
};
#endif
};
int64_t pts;
int64_t dts;
};
static void data_do_something(struct data *data)
{
data->buf += 10;
data->size -= 10;
}
static inline void frame_do_something(struct frame *frame)
{
data_do_something(&frame->d);
}
static void frame_do_specific_thing(struct frame *frame)
{
frame->buf -= 10;
frame->size += 10;
}
static void frame_print(struct frame *frame)
{
fprintf(stderr, "frame: data: %p %zu/%zu vs "
"%p %zu/%zu, pts: %" PRId64 "\n",
frame->d.buf, frame->d.size, frame->d.maxsize,
frame->buf, frame->size, frame->maxsize, frame->pts);
}
int main(void)
{
struct frame frame;
frame.d.size = frame.d.maxsize = 42;
frame.d.start = malloc(frame.d.size);
frame.d.buf = (uint8_t *) frame.d.start;
frame.d.next = NULL;
assert(frame.d.buf);
frame.pts = frame.dts = 72;
frame_print(&frame);
frame_do_something(&frame);
frame_print(&frame);
frame_do_specific_thing(&frame);
frame_print(&frame);
frame.next = &frame;
frame.d.next = &frame.d;
free(frame.d.start);
return 0;
}
More information about the vlc-devel
mailing list