Loading...
Searching...
No Matches
mjs_ffi.h
1/*
2 * Copyright (c) 2017 Cesanta Software Limited
3 * All rights reserved
4 */
5
6#ifndef MJS_FFI_H_
7#define MJS_FFI_H_
8
9#include "ffi/ffi.h"
10#include "mjs_ffi_public.h"
11#include "mjs_internal.h"
12
13#if defined(__cplusplus)
14extern "C" {
15#endif /* __cplusplus */
16
17#define MJS_CB_ARGS_MAX_CNT 6
18#define MJS_CB_SIGNATURE_MAX_SIZE (MJS_CB_ARGS_MAX_CNT + 1 /* return type */)
19
20typedef uint8_t mjs_ffi_ctype_t;
21
22enum ffi_sig_type {
23 FFI_SIG_FUNC,
24 FFI_SIG_CALLBACK,
25};
26
27/*
28 * Parsed FFI signature
29 */
31 /*
32 * Callback signature, corresponds to the arg of type MJS_FFI_CTYPE_CALLBACK
33 * TODO(dfrank): probably we'll need to support multiple callback/userdata
34 * pairs
35 *
36 * NOTE(dfrank): instances of this structure are grouped into GC arenas and
37 * managed by GC, and for the GC mark to work, the first element should be
38 * a pointer (so that the two LSBs are not used).
39 */
40 struct mjs_ffi_sig* cb_sig;
41
42 /*
43 * The first item is the return value type (for `void`, `MJS_FFI_CTYPE_NONE`
44 * is used); the rest are arguments. If some argument is
45 * `MJS_FFI_CTYPE_NONE`, it means that there are no more arguments.
46 */
47 mjs_ffi_ctype_t val_types[MJS_CB_SIGNATURE_MAX_SIZE];
48
49 /*
50 * Function to call. If `is_callback` is not set, then it's the function
51 * obtained by dlsym; otherwise it's a pointer to the appropriate callback
52 * implementation.
53 */
54 ffi_fn_t* fn;
55
56 /* Number of arguments in the signature */
57 int8_t args_cnt;
58
59 /*
60 * If set, then the signature represents the callback (as opposed to a normal
61 * function), and `fn` points to the suitable callback implementation.
62 */
63 unsigned is_callback : 1;
64 unsigned is_valid : 1;
65};
66typedef struct mjs_ffi_sig mjs_ffi_sig_t;
67
68/* Initialize new FFI signature */
69MJS_PRIVATE void mjs_ffi_sig_init(mjs_ffi_sig_t* sig);
70/* Copy existing FFI signature */
71MJS_PRIVATE void mjs_ffi_sig_copy(mjs_ffi_sig_t* to, const mjs_ffi_sig_t* from);
72/* Free FFI signature. NOTE: the pointer `sig` itself is not freed */
73MJS_PRIVATE void mjs_ffi_sig_free(mjs_ffi_sig_t* sig);
74
75/*
76 * Creates a new FFI signature from the GC arena, and return mjs_val_t which
77 * wraps it.
78 */
79MJS_PRIVATE mjs_val_t mjs_mk_ffi_sig(struct mjs* mjs);
80
81/*
82 * Checks whether the given value is a FFI signature.
83 */
84MJS_PRIVATE int mjs_is_ffi_sig(mjs_val_t v);
85
86/*
87 * Wraps FFI signature structure into mjs_val_t value.
88 */
89MJS_PRIVATE mjs_val_t mjs_ffi_sig_to_value(struct mjs_ffi_sig* psig);
90
91/*
92 * Extracts a pointer to the FFI signature struct from the mjs_val_t value.
93 */
94MJS_PRIVATE struct mjs_ffi_sig* mjs_get_ffi_sig_struct(mjs_val_t v);
95
96/*
97 * A wrapper for mjs_ffi_sig_free() suitable to use as a GC cell destructor.
98 */
99MJS_PRIVATE void mjs_ffi_sig_destructor(struct mjs* mjs, void* psig);
100
101MJS_PRIVATE int mjs_ffi_sig_set_val_type(mjs_ffi_sig_t* sig, int idx, mjs_ffi_ctype_t type);
102MJS_PRIVATE int
103 mjs_ffi_sig_validate(struct mjs* mjs, mjs_ffi_sig_t* sig, enum ffi_sig_type sig_type);
104MJS_PRIVATE int mjs_ffi_is_regular_word(mjs_ffi_ctype_t type);
105MJS_PRIVATE int mjs_ffi_is_regular_word_or_void(mjs_ffi_ctype_t type);
106
108 struct mjs_ffi_cb_args* next;
109 struct mjs* mjs;
110 mjs_ffi_sig_t sig;
111 mjs_val_t func;
112 mjs_val_t userdata;
113};
114typedef struct mjs_ffi_cb_args ffi_cb_args_t;
115
116/*
117 * cfunction:
118 * Parses the FFI signature string and returns a value wrapping mjs_ffi_sig_t.
119 */
120MJS_PRIVATE mjs_err_t mjs_ffi_call(struct mjs* mjs);
121
122/*
123 * cfunction:
124 * Performs the FFI signature call.
125 */
126MJS_PRIVATE mjs_err_t mjs_ffi_call2(struct mjs* mjs);
127
128MJS_PRIVATE void mjs_ffi_cb_free(struct mjs*);
129MJS_PRIVATE void mjs_ffi_args_free_list(struct mjs* mjs);
130
131#if defined(__cplusplus)
132}
133#endif /* __cplusplus */
134
135#endif /* MJS_FFI_H_ */
Definition mjs_ffi.h:107
Definition mjs_ffi.h:30
Definition mjs_core.h:63