19#include <XPLMPlugin.h>
26#define __INCLUDED_FROM_DR_C__
30#define DRE_MSG_ADD_DATAREF 0x01000000
31#define DR_TYPE_CHECK(__check_type, __type) \
32 __check_type ## _MSG(dr->type & (__type), \
33 "dataref \"%s\" has bad type %x (%s:%d: %s)", dr->name, \
34 dr->type, filename, line, varname)
35#define DR_WRITE_CHECK(__check_type) \
36 __check_type ## _MSG(dr->writable, "dataref \"%s\" is not writable " \
37 "(%s:%d: %s)", dr->name, filename, line, varname)
39static bool_t dre_plug_lookup_done = B_FALSE;
40static XPLMPluginID dre_plug = XPLM_NO_PLUGIN_ID;
41static XPLMPluginID drt_plug = XPLM_NO_PLUGIN_ID;
48 memset(dr, 0,
sizeof (*dr));
51 vsnprintf(dr->name, sizeof (dr->name), fmt, ap);
54 dr->dr = XPLMFindDataRef(dr->name);
56 memset(dr, 0,
sizeof (*dr));
59 dr->type = XPLMGetDataRefTypes(dr->dr);
60 VERIFY_MSG(dr->type & (xplmType_Int | xplmType_Float | xplmType_Double |
61 xplmType_IntArray | xplmType_FloatArray | xplmType_Data),
62 "dataref \"%s\" has bad type %x", dr->name, dr->type);
63 dr->writable = XPLMCanWriteDataRef(dr->dr);
70 return (dr->writable);
76 if (dr->type & xplmType_Int)
77 return (XPLMGetDatai(dr->dr));
78 if (dr->type & xplmType_Float)
79 return (XPLMGetDataf(dr->dr));
80 if (dr->type & xplmType_Double)
81 return (XPLMGetDatad(dr->dr));
82 if (dr->type & (xplmType_FloatArray | xplmType_IntArray |
89 VERIFY_MSG(0,
"dataref \"%s\" has bad type %x (%s:%d: %s)", dr->name,
90 dr->type, filename, line, varname);
97 if (dr->type & xplmType_Int) {
98 XPLMSetDatai(dr->dr, i);
99 }
else if (dr->type & xplmType_Float) {
100 XPLMSetDataf(dr->dr, i);
101 }
else if (dr->type & xplmType_Double) {
102 XPLMSetDatad(dr->dr, i);
103 }
else if (dr->type & (xplmType_FloatArray | xplmType_IntArray |
107 VERIFY_MSG(0,
"dataref \"%s\" has bad type %x (%s:%d: %s)",
108 dr->name, dr->type, filename, line, varname);
115 if (dr->type & xplmType_Double)
116 return (XPLMGetDatad(dr->dr));
117 if (dr->type & xplmType_Float)
118 return (XPLMGetDataf(dr->dr));
119 if (dr->type & xplmType_Int)
120 return (XPLMGetDatai(dr->dr));
121 if (dr->type & (xplmType_FloatArray | xplmType_IntArray |
128 VERIFY_MSG(0,
"dataref \"%s\" has bad type %x (%s%d: %s)", dr->name,
129 dr->type, filename, line, varname);
136 ASSERT_MSG(!isnan(f),
"%s (%s%d: %s)", dr->name, filename, line,
138 ASSERT_MSG(isfinite(f),
"%s (%s%d: %s)", dr->name, filename, line,
140 if (dr->type & xplmType_Double)
141 XPLMSetDatad(dr->dr, f);
142 else if (dr->type & xplmType_Float)
143 XPLMSetDataf(dr->dr, f);
144 else if (dr->type & xplmType_Int)
145 XPLMSetDatai(dr->dr, f);
146 else if (dr->type & (xplmType_FloatArray | xplmType_IntArray |
150 VERIFY_MSG(0,
"dataref \"%s\" has bad type %x (%s:%d: %s)",
151 dr->name, dr->type, filename, line, varname);
155dr_getvi_impl(
const dr_t *dr, DR_DEBUG_VARS,
int *i,
unsigned off,
unsigned num)
157 ASSERT(i != NULL || num == 0);
159 if (dr->type & xplmType_IntArray)
160 return (XPLMGetDatavi(dr->dr, i, off, num));
161 if (dr->type & xplmType_FloatArray) {
163 int n = XPLMGetDatavf(dr->dr, num > 0 ? f : NULL, off, num);
165 for (
int x = 0; x < n; x++)
171 if (dr->type & xplmType_Data) {
173 int n = XPLMGetDatab(dr->dr, num > 0 ? u : NULL, off, num);
175 for (
int x = 0; x < n; x++)
181 ASSERT_MSG(off == 0,
"Attempted read scalar dataref %s (type: %x) at "
182 "offset other than 0 (%d) (%s%d: %s)", dr->name, dr->type, off,
183 filename, line, varname);
190dr_setvi_impl(
const dr_t *dr, DR_DEBUG_VARS,
int *i,
unsigned off,
unsigned num)
194 if (dr->type & xplmType_IntArray) {
195 XPLMSetDatavi(dr->dr, i, off, num);
196 }
else if (dr->type & xplmType_FloatArray) {
198 for (
unsigned x = 0; x < num; x++)
200 XPLMSetDatavf(dr->dr, f, off, num);
202 }
else if (dr->type & xplmType_Data) {
204 for (
unsigned x = 0; x < num; x++)
206 XPLMSetDatab(dr->dr, u, off, num);
209 ASSERT_MSG(off == 0,
"Attempted write scalar dataref %s "
210 "(type: %x) at offset other than 0 (%d) (%s:%d: %s)",
211 dr->name, dr->type, off, filename, line, varname);
220 ASSERT(df != NULL || num == 0);
222 if (dr->type & xplmType_IntArray) {
224 int n = XPLMGetDatavi(dr->dr, num > 0 ? i : NULL, off, num);
226 for (
int x = 0; x < n; x++)
232 if (dr->type & xplmType_FloatArray) {
234 int n = XPLMGetDatavf(dr->dr, num > 0 ? f : NULL, off, num);
236 for (
int x = 0; x < n; x++)
242 if (dr->type & xplmType_Data) {
244 int n = XPLMGetDatab(dr->dr, num > 0 ? u : NULL, off, num);
246 for (
int x = 0; x < n; x++)
252 ASSERT_MSG(off == 0,
"Attempted read scalar dataref %s (type: %x) at "
253 "offset other than 0 (%d) (%s:%d: %s)", dr->name, dr->type, off,
254 filename, line, varname);
264 ASSERT(ff != NULL || num == 0);
266 if (dr->type & xplmType_IntArray) {
268 int n = XPLMGetDatavi(dr->dr, num > 0 ? i : NULL, off, num);
270 for (
int x = 0; x < n; x++)
276 if (dr->type & xplmType_FloatArray) {
277 int n = XPLMGetDatavf(dr->dr, ff, off, num);
280 if (dr->type & xplmType_Data) {
282 int n = XPLMGetDatab(dr->dr, num > 0 ? u : NULL, off, num);
284 for (
int x = 0; x < n; x++)
290 ASSERT_MSG(off == 0,
"Attempted read scalar dataref %s (type: %x) at "
291 "offset other than 0 (%d) (%s:%d: %s)", dr->name, dr->type, off,
292 filename, line, varname);
304 for (
unsigned x = 0; x < num; x++) {
305 ASSERT_MSG(!isnan(df[x]),
"%s[%d]", dr->name, x);
306 ASSERT_MSG(isfinite(df[x]),
"%s[%d]", dr->name, x);
308 if (dr->type & xplmType_IntArray) {
310 for (
unsigned x = 0; x < num; x++)
312 XPLMSetDatavi(dr->dr, i, off, num);
314 }
else if (dr->type & xplmType_FloatArray) {
316 for (
unsigned x = 0; x < num; x++)
318 XPLMSetDatavf(dr->dr, f, off, num);
320 }
else if (dr->type & xplmType_Data) {
322 for (
unsigned x = 0; x < num; x++)
324 XPLMSetDatab(dr->dr, u, off, num);
327 ASSERT_MSG(off == 0,
"Attempted write scalar dataref %s "
328 "(type: %x) at offset other than 0 (%d) (%s:%d: %s)",
329 dr->name, dr->type, off, filename, line, varname);
340 for (
unsigned x = 0; x < num; x++) {
341 ASSERT_MSG(!isnan(ff[x]),
"%s[%d]", dr->name, x);
342 ASSERT_MSG(isfinite(ff[x]),
"%s[%d]", dr->name, x);
344 if (dr->type & xplmType_IntArray) {
346 for (
unsigned x = 0; x < num; x++)
348 XPLMSetDatavi(dr->dr, i, off, num);
350 }
else if (dr->type & xplmType_FloatArray) {
351 XPLMSetDatavf(dr->dr, ff, off, num);
352 }
else if (dr->type & xplmType_Data) {
354 for (
unsigned x = 0; x < num; x++)
356 XPLMSetDatab(dr->dr, u, off, num);
359 ASSERT_MSG(off == 0,
"Attempted write scalar dataref %s "
360 "(type: %x) at offset other than 0 (%d) (%s:%d: %s)",
361 dr->name, dr->type, off, filename, line, varname);
371 DR_TYPE_CHECK(
VERIFY, xplmType_Data);
372 n = XPLMGetDatab(dr->dr, str, 0, cap > 0 ? cap - 1 : 0);
382 DR_TYPE_CHECK(
VERIFY, xplmType_Data);
384 XPLMSetDatab(dr->dr, str, 0, strlen(str));
391 DR_TYPE_CHECK(
VERIFY, xplmType_Data);
392 return (XPLMGetDatab(dr->dr, data, off, num));
399 DR_TYPE_CHECK(
VERIFY, xplmType_Data);
401 XPLMSetDatab(dr->dr, data, off, num);
405read_int_cb(
void *refcon)
410 ASSERT_MSG(dr->type & xplmType_Int,
"%s", dr->name);
411 if (dr->read_scalar_cb != NULL && dr->read_scalar_cb(dr, &value))
413 ASSERT_MSG(dr->value != NULL,
"%s", dr->name);
414 value = *(
int *)dr->value;
415 if (dr->read_cb != NULL)
416 dr->read_cb(dr, &value);
421write_int_cb(
void *refcon,
int value)
425 ASSERT_MSG(dr->type & xplmType_Int,
"%s", dr->name);
427 if (dr->write_scalar_cb != NULL && dr->write_scalar_cb(dr, &value))
429 ASSERT_MSG(dr->value != NULL,
"%s", dr->name);
430 if (dr->write_cb != NULL)
431 dr->write_cb(dr, &value);
432 *(
int *)dr->value = value;
436read_float_cb(
void *refcon)
440 ASSERT_MSG(dr->type & xplmType_Float,
"%s", dr->name);
443 if (dr->read_scalar_cb != NULL &&
444 dr->read_scalar_cb(dr, &value)) {
447 ASSERT_MSG(dr->value != NULL,
"%s", dr->name);
448 value = *(
double *)dr->value;
449 if (dr->read_cb != NULL)
450 dr->read_cb(dr, &value);
454 if (dr->read_scalar_cb != NULL &&
455 dr->read_scalar_cb(dr, &value)) {
458 ASSERT_MSG(dr->value != NULL,
"%s", dr->name);
459 value = *(
float *)dr->value;
460 if (dr->read_cb != NULL)
461 dr->read_cb(dr, &value);
467write_float_cb(
void *refcon,
float value)
471 ASSERT_MSG(dr->type & xplmType_Float,
"%s", dr->name);
473 if (dr->write_scalar_cb != NULL && dr->write_scalar_cb(dr, &value))
475 ASSERT_MSG(dr->value != NULL,
"%s", dr->name);
476 if (dr->write_cb != NULL)
477 dr->write_cb(dr, &value);
479 *(
double *)dr->value = value;
481 *(
float *)dr->value = value;
484#define DEF_READ_ARRAY_CB(typename, xp_typename, type_sz) \
486read_ ## typename ## _array_cb(void *refcon, typename *out_values, int off, \
491 ASSERT(dr != NULL); \
492 ASSERT_MSG(dr->type & xplmType_ ## xp_typename, "%s", dr->name); \
494 if (dr->read_array_cb != NULL) { \
495 int ret = dr->read_array_cb(dr, out_values, off, count); \
499 ASSERT_MSG(dr->value != NULL, "%s", dr->name); \
500 if (out_values == NULL) \
501 return (dr->count); \
502 if (off < dr->count) { \
503 count = MIN(count, dr->count - off); \
504 if (dr->stride == 0) { \
505 memcpy(out_values, dr->value + (off * type_sz), \
508 for (int i = 0; i < count; i++) { \
509 memcpy((void *)out_values + (i * type_sz), \
510 dr->value + ((off + i) * dr->stride), \
521#define DEF_WRITE_ARRAY_CB(typename, xp_typename, type_sz) \
523write_ ## typename ## _array_cb(void *refcon, typename *in_values, int off, \
528 ASSERT(dr != NULL); \
529 ASSERT_MSG(dr->type & xplmType_ ## xp_typename, "%s", dr->name); \
530 ASSERT_MSG(dr->writable, "%s", dr->name); \
531 ASSERT_MSG(in_values != NULL || count == 0, "%s", dr->name); \
533 if (dr->write_array_cb != NULL) { \
534 dr->write_array_cb(dr, in_values, off, count); \
537 ASSERT_MSG(dr->value != NULL, "%s", dr->name); \
538 if (off < dr->count) { \
539 count = MIN(count, dr->count - off); \
540 if (dr->stride == 0) { \
541 memcpy(dr->value + (off * type_sz), in_values, \
544 for (int i = 0; i < count; i++) { \
545 memcpy(dr->value + ((off + i) * dr->stride), \
546 ((void *)in_values) + (i * type_sz), \
553DEF_READ_ARRAY_CB(
int, IntArray,
sizeof (
int))
554DEF_WRITE_ARRAY_CB(
int, IntArray,
sizeof (
int))
555DEF_READ_ARRAY_CB(
float, FloatArray,
sizeof (
float))
556DEF_WRITE_ARRAY_CB(
float, FloatArray,
sizeof (
float))
557DEF_READ_ARRAY_CB(
void, Data,
sizeof (uint8_t))
558DEF_WRITE_ARRAY_CB(
void, Data,
sizeof (uint8_t))
560#undef DEF_READ_ARRAY_CB
561#undef DEF_WRITE_ARRAY_CB
569read_double_array_cb(
void *refcon,
float *out_values,
int off,
int count)
574 ASSERT_MSG(dr->type & xplmType_FloatArray,
"%s", dr->name);
576 if (dr->read_array_cb != NULL) {
577 int ret = dr->read_array_cb(dr, out_values, off, count);
581 ASSERT_MSG(dr->value != NULL,
"%s", dr->name);
582 if (out_values == NULL)
584 if (off < dr->count) {
586 (dr->stride != 0 ? dr->stride :
sizeof (double));
587 count = MIN(count, dr->count - off);
588 for (
int i = 0; i < count; i++) {
590 *(
double *)(dr->value + ((off + i) * stride));
600write_double_array_cb(
void *refcon,
float *in_values,
int off,
int count)
605 ASSERT_MSG(dr->type & xplmType_FloatArray,
"%s", dr->name);
607 ASSERT_MSG(in_values != NULL || count == 0,
"%s", dr->name);
609 if (dr->write_array_cb != NULL) {
610 dr->write_array_cb(dr, in_values, off, count);
613 ASSERT_MSG(dr->value != NULL,
"%s", dr->name);
614 if (off < dr->count) {
616 (dr->stride != 0 ? dr->stride :
sizeof (double));
617 count = MIN(count, dr->count - off);
618 for (
int i = 0; i < count; i++) {
619 *(
double *)(dr->value + ((off + i) * stride)) =
633dr_create_common(dr_t *dr, XPLMDataTypeID type,
void *value,
634 dr_cfg_t cfg, bool_t wide_type,
const char *fmt, va_list ap)
643 memset(dr, 0,
sizeof (*dr));
645 vsnprintf(dr->name, sizeof (dr->name), fmt, ap);
647 dr->dr = XPLMRegisterDataAccessor(dr->name, type, cfg.
writable,
648 read_int_cb, write_int_cb, read_float_cb, write_float_cb,
649 NULL, NULL, read_int_array_cb, write_int_array_cb,
650 wide_type ? read_double_array_cb : read_float_array_cb,
651 wide_type ? write_double_array_cb : write_float_array_cb,
652 read_void_array_cb, write_void_array_cb, dr, dr);
658 dr->count = cfg.
count;
667 dr->wide_type = wide_type;
669 if (!dre_plug_lookup_done) {
670 dre_plug = XPLMFindPluginBySignature(
671 "xplanesdk.examples.DataRefEditor");
672 drt_plug = XPLMFindPluginBySignature(
673 "com.leecbaker.datareftool");
674 dre_plug_lookup_done = B_TRUE;
676 if (dre_plug != XPLM_NO_PLUGIN_ID) {
677 XPLMSendMessageToPlugin(dre_plug, DRE_MSG_ADD_DATAREF,
680 if (drt_plug != XPLM_NO_PLUGIN_ID) {
681 XPLMSendMessageToPlugin(drt_plug, DRE_MSG_ADD_DATAREF,
691dr_create_i(dr_t *dr,
int *value, bool_t writable,
const char *fmt, ...)
697 dr_create_common(dr, xplmType_Int, value,
698 (
dr_cfg_t){ .count = 1, .writable = writable }, B_FALSE, fmt, ap);
709 dr_create_common(dr, xplmType_Int, value, cfg, B_FALSE, fmt, ap);
718dr_create_f(dr_t *dr,
float *value, bool_t writable,
const char *fmt, ...)
724 dr_create_common(dr, xplmType_Float, value,
725 (
dr_cfg_t){ .count = 1, .writable = writable }, B_FALSE, fmt, ap);
736 dr_create_common(dr, xplmType_Float, value, cfg, B_FALSE, fmt, ap);
745dr_create_f64(dr_t *dr,
double *value, bool_t writable,
const char *fmt, ...)
751 dr_create_common(dr, xplmType_Float, value,
752 (
dr_cfg_t){ .count = 1, .writable = writable }, B_TRUE, fmt, ap);
763 dr_create_common(dr, xplmType_Float, value, cfg, B_TRUE, fmt, ap);
769 const char *fmt, ...)
775 dr_create_common(dr, xplmType_IntArray, value,
776 (
dr_cfg_t){ .count = n, .writable = writable }, B_FALSE, fmt, ap);
787 dr_create_common(dr, xplmType_IntArray, value,
788 cfg, B_FALSE, fmt, ap);
794 const char *fmt, ...)
800 dr_create_common(dr, xplmType_FloatArray, value,
801 (
dr_cfg_t){ .count = n, .writable = writable }, B_FALSE, fmt, ap);
812 dr_create_common(dr, xplmType_FloatArray, value, cfg, B_FALSE, fmt, ap);
818 const char *fmt, ...)
824 dr_create_common(dr, xplmType_FloatArray, value,
825 (
dr_cfg_t){ .count = n, .writable = writable }, B_TRUE, fmt, ap);
836 dr_create_common(dr, xplmType_FloatArray, value, cfg, B_TRUE, fmt, ap);
842 const char *fmt, ...)
848 dr_create_common(dr, xplmType_Int | xplmType_IntArray, value,
849 (
dr_cfg_t){ .count = n, .writable = writable }, B_FALSE, fmt, ap);
855 const char *fmt, ...)
861 dr_create_common(dr, xplmType_Int | xplmType_IntArray, value,
862 cfg, B_FALSE, fmt, ap);
868 const char *fmt, ...)
874 dr_create_common(dr, xplmType_Float | xplmType_FloatArray, value,
875 (
dr_cfg_t){ .count = n, .writable = writable }, B_FALSE, fmt, ap);
881 const char *fmt, ...)
887 dr_create_common(dr, xplmType_Float | xplmType_FloatArray, value,
888 cfg, B_FALSE, fmt, ap);
894 const char *fmt, ...)
900 dr_create_common(dr, xplmType_Double | xplmType_FloatArray, value,
901 (
dr_cfg_t){ .count = n, .writable = writable }, B_TRUE, fmt, ap);
907 const char *fmt, ...)
913 dr_create_common(dr, xplmType_Double | xplmType_FloatArray, value,
914 cfg, B_TRUE, fmt, ap);
920 const char *fmt, ...)
926 dr_create_common(dr, xplmType_Data, value,
927 (
dr_cfg_t){ .count = n, .writable = writable }, B_FALSE, fmt, ap);
938 dr_create_common(dr, xplmType_Data, value, cfg, B_FALSE, fmt, ap);
948 if (dr->dr != NULL) {
949 XPLMUnregisterDataAccessor(dr->dr);
950 memset(dr, 0,
sizeof (*dr));
957 return (dr->cb_userinfo);
#define ASSERT_MSG(x, fmt,...)
#define VERIFY3S(x, op, y)
#define VERIFY_MSG(x, fmt,...)
#define VERIFY3U(x, op, y)
double dr_getf_impl(const dr_t *dr, const char *filename, int line, const char *varname)
void dr_setf_impl(const dr_t *dr, const char *filename, int line, const char *varname, double f)
void dr_array_set_stride(dr_t *dr, size_t stride)
void dr_create_vf_autoscalar_cfg(dr_t *dr, float *value, dr_cfg_t cfg, const char *fmt,...)
void dr_create_f_cfg(dr_t *dr, float *value, dr_cfg_t cfg, const char *fmt,...)
int dr_getvi_impl(const dr_t *dr, const char *filename, int line, const char *varname, int *i, unsigned off, unsigned num)
void dr_setvi_impl(const dr_t *dr, const char *filename, int line, const char *varname, int *i, unsigned off, unsigned num)
void dr_setvf_impl(const dr_t *dr, const char *filename, int line, const char *varname, double *df, unsigned off, unsigned num)
void dr_create_i_cfg(dr_t *dr, int *value, dr_cfg_t cfg, const char *fmt,...)
void dr_setvf32_impl(const dr_t *dr, const char *filename, int line, const char *varname, float *ff, unsigned off, unsigned num)
void dr_create_i(dr_t *dr, int *value, bool_t writable, const char *fmt,...)
void dr_seti_impl(const dr_t *dr, const char *filename, int line, const char *varname, int i)
void dr_create_vf(dr_t *dr, float *value, size_t n, bool_t writable, const char *fmt,...)
void dr_create_f64_cfg(dr_t *dr, double *value, dr_cfg_t cfg, const char *fmt,...)
void dr_create_f(dr_t *dr, float *value, bool_t writable, const char *fmt,...)
void dr_create_vf64_autoscalar(dr_t *dr, double *value, size_t n, bool_t writable, const char *fmt,...)
void dr_create_vf64_cfg(dr_t *dr, double *value, dr_cfg_t cfg, const char *fmt,...)
void dr_create_b_cfg(dr_t *dr, void *value, dr_cfg_t cfg, const char *fmt,...)
bool_t dr_find(dr_t *dr, const char *fmt,...)
void dr_create_vf_autoscalar(dr_t *dr, float *value, size_t n, bool_t writable, const char *fmt,...)
void dr_create_f64(dr_t *dr, double *value, bool_t writable, const char *fmt,...)
int dr_geti_impl(const dr_t *dr, const char *filename, int line, const char *varname)
void dr_create_b(dr_t *dr, void *value, size_t n, bool_t writable, const char *fmt,...)
void dr_create_vf64_autoscalar_cfg(dr_t *dr, double *value, dr_cfg_t cfg, const char *fmt,...)
void dr_create_vi_cfg(dr_t *dr, int *value, dr_cfg_t cfg, const char *fmt,...)
void dr_create_vi_autoscalar(dr_t *dr, int *value, size_t n, bool_t writable, const char *fmt,...)
void dr_create_vi(dr_t *dr, int *value, size_t n, bool_t writable, const char *fmt,...)
void dr_sets_impl(const dr_t *dr, const char *filename, int line, const char *varname, char *str)
void dr_setbytes_impl(const dr_t *dr, const char *filename, int line, const char *varname, void *data, unsigned off, unsigned num)
void dr_create_vi_autoscalar_cfg(dr_t *dr, int *value, dr_cfg_t cfg, const char *fmt,...)
int dr_getbytes_impl(const dr_t *dr, const char *filename, int line, const char *varname, void *data, unsigned off, unsigned num)
void dr_create_vf64(dr_t *dr, double *value, size_t n, bool_t writable, const char *fmt,...)
void dr_create_vf_cfg(dr_t *dr, float *value, dr_cfg_t cfg, const char *fmt,...)
int dr_getvf_impl(const dr_t *dr, const char *filename, int line, const char *varname, double *df, unsigned off, unsigned num)
void * dr_get_cb_userinfo(const dr_t *dr)
int dr_gets_impl(const dr_t *dr, const char *filename, int line, const char *varname, char *str, size_t cap)
int dr_getvf32_impl(const dr_t *dr, const char *filename, int line, const char *varname, float *ff, unsigned off, unsigned num)
bool_t dr_writable(dr_t *dr)
static void * safe_malloc(size_t size)
bool writable
Defines whether this dataref will be writable or read-only.
int(* read_array_cb)(dr_t *dr, void *values_out, int off, int cnt)
void(* write_cb)(dr_t *dr, void *value_in)
bool_t(* write_scalar_cb)(dr_t *dr, void *value_in)
bool_t(* read_scalar_cb)(dr_t *dr, void *value_out)
void(* write_array_cb)(dr_t *dr, void *values_in, int off, int cnt)
void(* read_cb)(dr_t *dr, void *value_out)