File: calls.c

package info (click to toggle)
fungw 1.2.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,268 kB
  • sloc: ansic: 24,257; makefile: 500; sh: 32; awk: 9; perl: 8; tcl: 7; javascript: 7; ruby: 7; python: 6
file content (101 lines) | stat: -rw-r--r-- 3,750 bytes parent folder | download | duplicates (3)
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <stdlib.h>
#include <stdio.h>
/*#include <string.h>
#include <ctype.h>*/
#include <assert.h>
#include <libfungw/fungw.h>
#include <libfungwbind/c/fungw_c.h>

double wrap_avg(fgw_ctx_t *ctx, double a, double b);

/* Import fawk init; this relies on two things:
   - fawk is always available in fungw, no external dep (well, the user can
     disable it in ./configure that'd lead to link error here)
   - fawk is in the big static lib (.a) of all languages and if we call its
     init, all relevant objects will get linked
*/
extern int pplg_init_fungw_fawk(void);

int main(int argc, char *argv[])
{
	fgw_ctx_t ctx;
	fgw_arg_t res, arg[8];
	fgw_error_t err;
	fgw_obj_t *sobj;
	fgw_func_t *func_avg;
	char *sres;

	/* Initialize and register the script language engine fawk */
	pplg_init_fungw_fawk();

	/* initialize a context */
	fgw_init(&ctx, "host");

	/* create objects for the script: loads script and runs its main() */
	sobj = fgw_obj_new(&ctx, "avg_script", "fawk", "avg.fawk", NULL);
	assert(sobj != NULL);

	/* Get a function handle knowing the short name of the function */
	func_avg = fgw_func_lookup(&ctx, "avg");
	if (func_avg == NULL) {
		fprintf(stderr, "Error: failed to find global function avg\n");
		return 1;
	}

	/* Manual call: no helper, just raw call to the function pointer */
	arg[0].type = FGW_FUNC;
	arg[0].val.argv0.func = func_avg;
	arg[0].val.argv0.user_call_ctx = NULL;
	arg[1].type = FGW_DOUBLE;
	arg[1].val.nat_double = 42;
	arg[2].type = FGW_DOUBLE;
	arg[2].val.nat_double = 71;
	err = func_avg->func(&res, 3, arg);
	printf("direct: err=%d rt=%x rv=%.2f\n", err, res.type, res.val.nat_double);

	/* Dtring based call. The callee gets each argument as a string
	   (in this particular case the callee will convert them to double within
	   fawk by doing arithmetics on them). Result is always an allocated
	   (char *) string (so fungw will convert the script returned double
	   to a newly allocated string). This slow calling convention may be
	   useful if input and output is string based for some reason, e.g.
	   when implementing a CLI. */
	sres = fgw_scall(&ctx, "avg", "42", "71", NULL);
	printf("scall: sres='%s'\n", sres);
	free(sres);

	/* Type/data based call, using generic vararg wrapper; this saves all the
	   unnecessary string conversions in this example. Of course any argument
	   may be passed as a different type, even a string, if that's what is
	   available at a time - the script binding code or the script will
	   do the necessary conversion. Since this is a script, we shouldn't rely
	   on the return value type being double - rather convert it. If it is
	   a double, the conversion is a noop. Note: in vararg calls, numeric args
	   shall be explicitly casted: without the (double) cast here, these
	   numbers could easily pass as integers causing wrong readout on the other
	   side! */
	err = fgw_vcall(&ctx, &res, "avg",   FGW_DOUBLE, (double)42,   FGW_DOUBLE, (double)71,   0);
	fgw_arg_conv(&ctx, &res, FGW_DOUBLE);
	printf("vcall: err=%d rt=%x rv=%.2f\n", err, res.type, res.val.nat_double);

	/* Use local wrapper so the call feels native in C */
	printf("wrap: %.2f\n", wrap_avg(&ctx, 42, 77));

	/* clean up and exit */
	fgw_uninit(&ctx);
	fgw_atexit();
	return 0;
}


/* Emulate a native C function: use the vararg based shorthand and convert
   the result to double. The drawback of this overly simple API is the
   inability of error reporting. Of course the code could check the return
   value of fgw_vcall() and fgw_arg_conv() and report error. */
double wrap_avg(fgw_ctx_t *ctx, double a, double b)
{
	fgw_arg_t res;
	fgw_vcall(ctx, &res, "avg",   FGW_DOUBLE, a,   FGW_DOUBLE, b,   0);
	fgw_arg_conv(ctx, &res, FGW_DOUBLE);
	return res.val.nat_double;
}