File: args_structure.inc

package info (click to toggle)
critcl 3.3.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 9,680 kB
  • sloc: ansic: 41,058; tcl: 12,090; sh: 7,230; pascal: 3,456; asm: 3,058; ada: 1,681; cpp: 1,001; cs: 879; makefile: 333; perl: 104; xml: 95; f90: 10
file content (79 lines) | stat: -rw-r--r-- 2,413 bytes parent folder | download
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
[comment {-*- mode: tcl ; fill-column: 90 -*-}]

[list_begin enumerated]

[enum] For all that this is a part of how to
[sectref {Using External Libraries} {Use External Libraries}], for the demonstratation
only the basics are needed.

[enum][vset base][example {
    critcl::ccode {
	typedef struct vec2 {
	    double x;
	    double y;
	} vec2;

	typedef vec2* vec2ptr;

	int
	GetVecFromObj (Tcl_Interp* interp, Tcl_Obj* obj, vec2ptr* vec)
	{
	    int len;
	    if (Tcl_ListObjLength (interp, obj, &len) != TCL_OK) return TCL_ERROR;
	    if (len != 2) {
		Tcl_SetObjResult (interp, Tcl_ObjPrintf ("Expected 2 elements, got %d", len));
		return TCL_ERROR;
	    }

	    Tcl_Obj* lv[2];
	    if (Tcl_ListObjGetElements (interp, obj, &lv) != TCL_OK) return TCL_ERROR;

	    double x, y;
	    if (Tcl_GetDoubleFromObj (interp, lv[0], &x) != TCL_OK) return TCL_ERROR;
	    if (Tcl_GetDoubleFromObj (interp, lv[1], &y) != TCL_OK) return TCL_ERROR;

	    *vec = Tcl_Alloc (sizeof (vec2));
	    (*vec)->x = x;
	    (*vec)->y = y;
	    return TCL_OK;
	}
    }

    critcl::argtype vec2 {
	if (GetVecFromObj (interp, @@, &@A) != TCL_OK) return TCL_ERROR;
    } vec2ptr vec2ptr

    critcl::argtyperelease vec2 {
	/* @A : C variable holding the data to release */
	Tcl_Free ((char*) @A);
    }

    critcl::cproc norm {vec2 vector} double {
	double norm = hypot (vector->x, vector->y);
	return norm;
    }
}][vset rebuild]

[enum] The structure to pass as argument is a 2-dimensional vector. It is actually passed
in as a pointer to a [type vec2] structure.

This pointer is created by the [fun GetVecFromObj] function. It allocates and fills the
structure from the Tcl value, which has to be a list of 2 doubles. The bulk of the code in
[fun GetVecFromObj] is for verifying this and extracting the doubles.

[enum] The [cmd argtyperelease] code releases the pointer when the C function returns. In
other words, the pointer to the structure is owned by the translation layer and exists
only while the function is active.

[enum] While working this code has two disadvantages.

First there is memory churn. Each call of [cmd norm] causes the creation and release of a
temporary [type vec2] structure for the argument.

Second is the need to always extract the data from the [type Tcl_Obj*] value.

[para] Both can be done better.

[para] We will come back to this after explaining how to return structures to Tcl.

[list_end]