1
2
3
4
5
6
7
8
9
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
|
/* libmisc/tests/test_vcall.c - Tests for <libmisc/vcall.h>
*
* Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <libmisc/assert.h>
#include <libmisc/vcall.h>
#include "test.h"
/******************************************************************************/
struct frobber_vtable;
typedef struct {
struct frobber_vtable *vtable;
} implements_frobber;
struct frobber_vtable {
int (*frob)(implements_frobber *);
int (*frob1)(implements_frobber *, int);
void (*frob0)(implements_frobber *);
};
/******************************************************************************/
struct myclass {
int a;
implements_frobber;
};
static_assert(offsetof(struct myclass, implements_frobber) != 0);
static int myclass_frob(implements_frobber *_self) {
struct myclass *self = VCALL_SELF(struct myclass, implements_frobber, _self);
test_assert(self);
test_assert((void*)self != (void*)_self);
return self->a;
}
static int myclass_frob1(implements_frobber *_self, int arg) {
struct myclass *self = VCALL_SELF(struct myclass, implements_frobber, _self);
test_assert(self);
test_assert((void*)self != (void*)_self);
return arg;
}
static void myclass_frob0(implements_frobber *_self) {
struct myclass *self = VCALL_SELF(struct myclass, implements_frobber, _self);
test_assert(self);
test_assert((void*)self != (void*)_self);
}
struct frobber_vtable myclass_vtable = {
.frob = myclass_frob,
.frob1 = myclass_frob1,
.frob0 = myclass_frob0,
};
/******************************************************************************/
#define MAGIC1 909837
#define MAGIC2 657441
int main() {
struct myclass obj = {
.implements_frobber = { .vtable = &myclass_vtable },
.a = MAGIC1,
};
test_assert(VCALL(&obj, frob) == MAGIC1);
test_assert(VCALL(&obj, frob1, MAGIC2) == MAGIC2);
VCALL(&obj, frob0);
return 0;
}
|