2
Newly introduced with critcl version 3 is the support for stubs
3
tables, Tcl's dynamic linking mechanism handling the resolution of
4
symbols between C extensions.
6
We won't go into its details here. See [uri http://wiki.tcl.tk/285]
7
for an introduction in general, and section [sectref {Stubs Tables}]
8
for the details of critcl's particular variant.
10
[para] Critcl supports this via a single command, [cmd critcl::api],
13
[para] First, importing stubs tables, i.e. APIs, from another
16
[list_begin definitions]
17
[comment ---------------------------------------------------------------------]
18
[call [cmd ::critcl::api] [method import] [arg name] [arg version]]
20
Critcl prepares the [file .critcl] file [emph and] its companion
21
[file .c] files by including the headers
23
[list_begin enumerated]
24
[enum] [file [var name]/[var name]Decls.h]
25
[enum] [file [var name]/[var name]StubLib.h]
28
in the appropriate places. It is checked that the compiler will be
29
able to find these header files somewhere on the include search
30
path, using the paths defined so far (See [cmd critcl::cheaders], and
31
the critcl application's [option -I] and [option -includedir]
32
options). Note how critcl expects the headers of package [var foo] to
33
reside in a sub-directory [file foo] of the known include search
36
[para] [emph Important:] If [var foo] is a namespaced package name,
37
like, for example "c::stack", then the namespace separators "::" are
38
converted into underscores ("_") in path names, C code, etc.
40
[para] The first header is expected to contain contains all the
41
necessary stubs table type declarations, mapping macros, etc., and may
42
include package specific headers (See [cmd {critcl::api header}]
45
This header is included at the beginning of the C code backing the
46
[file .critcl] file, and at the beginning of all companion [file .c]
47
files. This means that the writer of these files doesn't have to write
48
the necessary [term {#include}] directory, critcl does it for them.
50
[para] The second header is expected to contain the stubs table
51
variable definition, and the C code, i.e. definition, of the function
54
This, and a call to this initializer function are added to the
55
[file .critcl] file's initialization code.
57
[para] If the directory containing the aforementioned headers also
58
contains the file [file [var name]/[var name].decls] then it is
59
assumed that this file contains the external representation of the
60
stubs table used to generate the headers. The file is read and the
61
internal representation of the stubs table returned as result of the
62
command, for the importing package to use as it sees fit. If no such
63
file is present the command returns the empty string as its result.
65
[para] One possible use would be the automatic generation of C code
66
calling on the functions listed in the imported API.
68
[para] When generating a TEA wrapper the names of the imported APIs
69
are used to declare [syscmd configure] options with which the user can
70
declare a non-standard location for the headers of the API. Any API
71
[var FOO] is translated a single configure option
72
[option --with-[var FOO]-include].
77
[para] Second, declaration and export of a stubs table, i.e. API, for
78
the current package, [var foo]:
80
[list_begin definitions]
81
[comment ---------------------------------------------------------------------]
82
[call [cmd ::critcl::api] [method function] [arg resulttype] [arg name] [arg arguments]]
84
This method declares that the function [arg name] is in the public API
85
of the package, and its signature (type of the result, number, names
86
and types of its arguments).
88
Using this method automatically causes critcl to generate both the
89
code for a stubs table in the package, the headers needed by packages
90
using this API, and a [file .decls] file containing the stubs table
91
implied by the exports, usable by [cmd {critcl::api import}].
93
[para] [arg arguments] is a list of C types and associated argument
94
names. Like a dictionary, except that keys (argument names) and values
95
(argument types) are swapped. The [arg resulttype] is a C type as well.
97
[comment ---------------------------------------------------------------------]
98
[call [cmd ::critcl::api] [method header] [opt [arg pattern]...]]
100
This method notifies critcl of companion header files which have to be
101
exported together with the generated stubs headers.
103
[para] All arguments are interpreted as glob pattern and the matching
104
files are copied into the directory containing the generated headers
105
well. As an importing package uses only [file [var foo]Decls.h] to
106
access the API this generated header will contain the necessary
107
[term {#include}] directives to make these companion header files and their
108
declarations available too.
110
Patterns matching no file or non-existing files cause the command to
113
[para] [emph Note] that patterns which are not beginning with an
114
absolute path are interpreted relative to the directory containing the
115
current [file .critcl] file.
118
I am intentionally not documenting "critcl::api export".
119
I am not convinced yet that this methis is needed.
120
The default, using the package name as the stubs table
121
library and interface names seems to me to be not only
122
reasonable, but the only setting truly needed. I simply
123
do not see a use case for having the library and interface
124
named different than the package.
125
(In a bundle, like tcllibc each bundled package still declares
129
[comment ---------------------------------------------------------------------]
130
[call [cmd ::critcl::api] [method extheader] [opt [arg file]...]]
132
This method is similar [cmd {::critcl::api header}], in that it
133
notifies critcl of companion header files which have to be exported
134
together with the generated stubs headers.
136
[para] The difference is that these headers will be expected to exist
137
in the external development environment.
139
As such they will be [term {#include}]d in the generated header for
140
the package, but not copied to the package header directory. Nor are
141
they allowed to be glob patterns, as critcl has no context, i.e
142
directory, in which to expand such patterns.
146
Note that the generated headers for an exported API are included in
147
the package like it is done when importing it somewhere else. To repeat:
149
[para] The [file [var foo]Decls.h] header is included at the beginning
150
of the C code backing the [file .critcl] file, and at the beginning of
151
all companion [file .c] files. This means that the writer of these
152
files doesn't have to write the necessary [term {#include}] directory,
153
critcl does it for them.
155
[para] In mode "compile & run" the generated header files, and their
156
companion headers, if any, are placed in the subdirectory [file foo]
157
of the [sectref {Result Cache}]. As this location is implicitly added
158
to the include search path any other package importing this API and
159
and build in mode "compile & run" as well will find the these headers.
161
[para] For mode "generate package" the application was extended with a
162
new option [option -includedir] which specifies the location to place
163
the generated headers in (again in subdirectory [file foo] of that
164
path). This path is also be added to the include search paths,
165
ensuring that a package importing an API will find it if the package
166
exporting that API used the same setting for [option -includedir].
168
[para] For mode "generate TEA" the static scanner was extended to
169
recognize [cmd {critcl::api header}] as a source of companion files.
170
It further uses data about [cmd {critcl::api import}] commands to put
171
proper support for [option --with-[var foo]-include] options into the
172
generate [file configure(.in)] so that a user may specify custom
173
locations for the headers of any imported API.