Objective-Everything Release 5. Copyright ©1994-1998 by TipTop Software, Inc. All Rights Reserved.
Objective-Tcl facilitates direct and seamless interaction with compiled C code and data structures.
All Objective-Tcl procedures live in the objtcl:: namespace. This namespace is, by default, imported into global namespace so that you normally do not have to prefix ObjTcl commands with objtcl::
All C symbols normally live in the c:: namespace. By default, all the symbols in the C namespace can be directly accessed in the global namespace.
The Objective-Everything system maintains a global table of type names and symbol names. When the system starts up, it loads these tables from the module directories of each module that is loaded: Mod.framework/Resources/Mod.cfun, where, Mod is ObjCore, ObjAppKit, ObjTcl, ObjPy, etc. In addition, any user-specific definitions provided in ~/.AppInfo/Objective/User.cfun will be automatically loaded at startup as well. At runtime, you can explicitly load any additional definitions.
NOTE: ObjTcl gives you full and unrestricted access to C. Although ObjTcl by default does check for invalid memory access and such, just like in C, be careful not to crash the system.
All of the examples below are executed in an AppKit interactor. To run an AppKit interactor, simply double-click on ObjShell.app. Alternatively, run objtclsh, type appkit::run, and then click Objective->Interact->Interactor and select "Tcl". This is only relevant because some examples below operate on the $NSApp object which is non-existent or nil if the appkit is not running, or invoke the NSRunAlertPanel() function.
In Objective-Tcl, you use the standard C/ObjC syntax to specify types. All C/ObjC types are supported.
Declare/define C stuff, i.e., types, functions, globals, classes, categories, protocols, etc., using the C/ObjC syntax.
Example:
tcl% cdef { %--> struct mystruct { %--> int anInt; %--> double aDouble; %--> id anObject; %--> char *aString; %--> NSArray *anArray; %--> }; %--> typedef struct mystruct *xyz; %--> double cos(double); %--> extern int errno; > }
This registers "struct mystruct" and type "xyz" in the global C type table. It also registers function "cos" and global "errno" with the specified prototypes in the global symbol table.
Returns extended ObjC type encoding for the given type.
Example:
tcl% tencode char c tcl% tencode {char *} * tcl% tencode NSRect {?="origin"{?="x"f"y"f}"size"{?="width"f"height"f}} tcl% tencode {union { int x; char *y; float d;}} ("x"i"y"*"d"f) tcl% tencode {int func(double dbl, float flt)} <"func"i"dbl"d"flt"f> tcl% tencode xyz ^{mystruct="anInt"i"aDouble"d"anObject"@"aString"*"anArray"@} tcl% tencode {struct mystruct} {mystruct="anInt"i"aDouble"d"anObject"@"aString"*"anArray"@} tcl% tencode cos
Returns extended ObjC type encoding for the given type.
Example:
tcl% tdecode {{?="origin"{?="x"f"y"f}"size"{?="width"f"height"f}}} NSRect tcl% tdecode r* const STR tcl% tdecode [tencode {struct mystruct}] struct mystruct
Returns expanded type.
Example:
tcl% texpand NSRect struct { struct { float x; float y; } origin; struct { float width; float height; } size; }
Returns byte size of type.
Example:
tcl% sizeof NSRect 16
Returns byte alignment of type.
Example:
tcl% alignof NSRect 4
In ObjTcl, C data is represented by the C datum type. Every C datum has two properties: type and address. Use typeof and addrof procedures to get these properties respectively. There are two main C datum subtypes: pointer datum and function datum.
ObjTcl C datum type is represented as a Tcl string of the form type@address where type is the datum's extended type encoding, and address is the datum's address.
A pointer datum represents a value stored in memory.
Returns the datum which is registered in the global symbol table with name. This is really an identity function.
Example: NSApp is registered in the global C symbol table.
tcl% ptr NSApp NSApp tcl% typeof [ptr NSApp] id tcl% addrof [ptr NSApp] 0x62598a4
Creates a duplicate of the datum.
Creates and returns a datum of specified type with specified address. Address can be symbolic, or given as another datum. If the address is given as a datum ptr essentially casts the datum to the specified type.
Example: NSApp is registered in the global C symbol table.
# NULL pointer of type int tcl% set p [ptr int 0x0] ^i@0x0 tcl% typeof $p int tcl% addrof $p 0x0
# Cast NSApp to int pointer tcl% set a [ptr int NSApp] ^i@NSApp tcl% typeof $a int tcl% addrof $a 0x62598a4
Casts object to datum. This essentially is an identity operation since objects are C data.
Example:
tcl% set app [NSApplication sharedApplication] @TTApplication@a795c tcl% set app_as_ptr [ptr $app] @TTApplication@a795c tcl% typeof $app_as_ptr struct { Class isa; id _nextResponder; NSEvent* _currentEvent; ... }
# or, simply: tcl% typeof $app ...
Tcl values which have '&' as the first character are treated as C data of type char[n], where n is the length of the Tcl string value, and the address being a pointer to the actual second character of the Tcl string. This is sometimes useful as a shortcut if you need a static character buffer; you don't need to malloc the data, you just use the storage allocated for the Tcl value itself. Be careful when you use this because when the Tcl value is gone, the C datum that it represented will point into deallocated memory.
tcl% set buf "&01234567890123456789" &01234567890123456789 tcl% typeof $buf char [21] tcl% addrof $buf 0x118d39 tcl% store $buf "Hello World!" tcl% set buf &Hello World\03456789 tcl% fetch $buf Hello World!\03456789
The NULL procedure returns a special, unique NULL value which acts just like [ptr void 0x0], but it has no printable representation. This value is returned as a result of invoking a C function or method which returns a NULL value.
Tests whether the datum is the special NULL value.
Example:
tcl% NULL tcl% thenullp [ptr void 0x0] 0 tcl% thenullp [NULL] 1 tcl% typeof [NULL] void tcl% addrof [NULL] 0x0
Allocates cnt items of the specified type and returns a pointer datum to the allocated memory.
Reallocates pointer datum to hold cnt items
Frees memory pointed to by ptr.
Pointer arithmetic: offset pointer.
Fetches (dereferences) the value pointed to by ptr. Index
idx can be used to specify subdatum.
You can also fetch the value of the (entire) ptr datum by "calling"
the datum.
The index is a list specifying a path to a subdatum. Each element of the list can be:
Stores value val into the specified (sub)datum.
Example:
# Allocate a NSRect, store a value in it, read some values tcl% set p [malloc NSRect] ^{?="origin"{?="x"f"y"f}"size"{?="width"f"height"f}}@0x56174 tcl% store $p {{1 2} {3 4}} tcl% fetch $p {1.0 2.0} {3.0 4.0} tcl% fetch $p origin 1.0 2.0 tcl% fetch $p {size width} 3.0 tcl% fetch $p {1 0} 3.0
# Reallocate p; access the second element tcl% set p [realloc $p 2] ^{?="origin"{?="x"f"y"f}"size"{?="width"f"height"f}}@0x56174 tcl% set p2 [offset $p 1] ^{?="origin"{?="x"f"y"f}"size"{?="width"f"height"f}}@0x56184 tcl% store $p2 {{5 6} {7 8}}
# Free p tcl% set p [free $p] ^{?="origin"{?="x"f"y"f}"size"{?="width"f"height"f}}@0x0
# Store/fetch index tcl% set q [malloc {NSPoint [5]}] ^[5{?="x"f"y"f}]@0x561a8 tcl% texpand [typeof $q] struct { float x; float y; } [5] tcl% store $q {2 x} 123 tcl% fetch $q {0.0 0.0} {0.0 0.0} {123.0 0.0} {0.0 0.0} {0.0 0.0}
# & operator returns the item address tcl% fetch $q & ^[5{?="x"f"y"f}]@0x561a8 # I.e., this is $q itself
# Get the address of q[2].y: q2y=&(q[2].y); tcl% set q2y [fetch $q {2 y &}] ^f@0x561bc tcl% store $q2y {456} tcl% $q {0.0 0.0} {0.0 0.0} {123.0 456.0} {0.0 0.0} {0.0 0.0}
tcl% set q [free $q] ^[5{?="x"f"y"f}]@0x0
tcl% set app [NSApplication sharedApplication] @TTApplication@a795c
# Fetch all instance variables of an object at once tcl% fetch $app TTApplication nil @NSEvent@15bfc8 @NSConcreteMutableArray@a1210 ...
# Get a pointer to an instance variable tcl% set currentEventPtr [fetch $app {_currentEvent &}] ^@'NSEvent'@0xa7964 # Get the value pointed to tcl% fetch $currentEventPtr @NSEvent@147904 tcl% * [fetch $currentEventPtr] NSEvent: type=KeyDown loc=(0,0) time=...
C function datum is used to invoke a C function
Returns a function which is registered in the global symbol table with name. This is really an identity function.
Example:
tcl% typeof [fun NSBeep] void ()()
Creates a duplicate of the function.
Creates and returns a function of specified type with specified entry point address. Address can be symbolic, or given as another datum. If the address is given as a datum fun essentially casts the datum to the specified function type.
Example:
tcl% set pf [fun {void printf(const char *format, int x, char *y)} printf] <"printf"v"format"r*"x"i"y"*>@printf tcl% call $pf "Hello World!! int=%d, char*=%s\n" 123 "abc" # stdout: Hello World!! int=123, char*=abc
Casts a method into a function.
Example:
tcl% set mm [fun $app mainMenu] <"mainMenu"@"self"@"_cmd":>@0x6081b20 tcl% typeof $mm id mainMenu(id self, SEL _cmd) tcl% call $mm $app mainMenu @NSMenu@b01e8 tcl% [$mm $app mainMenu] setTitle: "Hello"
Invokes a function with arguments.
Example:
tcl% cos 1 0.540302305868 tcl% NSRunAlertPanel "ObjTcl" "Hello World!" [nil] [nil] [nil] 1
Defines a global datum with name, and makes it available as a Tcl global variable.
Example:
tcl% defglob NSApp tcl% set NSApp @TTApplication@a795c tcl% defglob NSApp_as_int [ptr int NSApp] tcl% addrof NSApp 0x62598a4 tcl% addrof NSApp_as_int 0x62598a4 tcl% typeof NSApp_as_int int tcl% addrof $NSApp 0xa795c tcl% format "0x%x" $NSApp_as_int 0xa795c
Defines a global constant with name and associated value, and makes it available as a Tcl global variable
Example:
tcl% defconst MyRect NSRect {{12 34} {56 78}} tcl% puts [MyRect] {12.0 34.0} {56.0 78.0}
Defines a function with name.
Example: Make alert be an alias for NSRunAlertPanel
tcl% defun alert NSRunAlertPanel
Tcl uses the "everything is a string" type model. In ObjTcl, types are used for instance variable, global variable, method and function prototype declaration. ObjTcl automatically converts from primitive C/ObjC types to Tcl values and vice versa when required. This conversion occurs:
The type table in the previous section lists the conversion functions that are used when converting from Tcl string values to ObjC type values and vice versa. Here is a description of what each type conversion does.
Tcl->C: If the Tcl string value represents an object or a class,
that's the result of conversion. If the object does not directly
represent the object the following will happen: If the
autoconversion is OFF, an exception is raised. If autoconversion is
ON (the default behavior), the Tcl string value will be converted to an
NSString.
C->Tcl: A Tcl string value representing the object is the result
of conversion. In addition, the object is registered with the
Objective-Everything system, and the system will detect when the object
becomes invalid.
Tcl->C: Tcl values map to strings directly, with the exception that
the ObjTcl [NULL] value is converted to
NULL string.
C->Tcl: C strings map to Tcl values directly, with the exception
that the NULL C string value is converted to the [NULL]
ObjTcl value.
Tcl->C: Tcl string value is mapped to ObjC SEL type using the
standard sel_getName() function. [NULL] Tcl
values are mapped to NULL selectors
C->Tcl: ObjC SEL type is directly converted to Tcl string value
using the sel_getUid() function. NULL selectors are
converted to the [NULL] Tcl value.
Note that C char type is treated as an 8-bit integer. You may use the ord ObjTcl procedure to convert ASCII characters to corresponding integer values. C bitfields are also treated as integer numbers.
Tcl->C: The standard Tcl "to-integer" conversion is used.
C->Tcl: The standard integer-to-string conversion is used.
Tcl string | C int |
---|---|
0xff | 255 |
'A' | 65 |
123 | 123 |
yes | 1 |
no | 0 |
Tcl->C: The standard Tcl "to-double" conversion is used.
C->Tcl: The standard double-to-string conversion is used.
Tcl->C: The ObjTcl C datum type is converted
to the C pointer by taking the address of the datum.
C->Tcl: C pointers are converted to the ObjTcl C datum type with
the corresponding type and address.
C structs are represented as Tcl lists (i.e., struct elements correspond to Tcl list elements) For example: struct { int x=123; float y=4.5; }; is represented as {123 4.5}.
Tcl->C: Each element of the Tcl list representing the structure is
converted to the coresponding structure element.
C->Tcl: Elements of the C structure are converted to Tcl values
and packed into a Tcl list.
C unions are represented as Tcl lists. The first element of the list is used to indicate which element value the second element of the list is representing. If the first element is -1, the rest of the list contains all the union elements.
Tcl->C: Based on what the first element of the list is, appropriate conversion is performed. For example, consider:
union { int x; float y; } u;
Storing {0 123} into u is equivalent to u.x=123;
Storing {1 4.5} is equivalent to u.y=4.5;
Storing {-1 123 4.5} is eqivalent to u.x=123;
u.y=4.5;
C->Tcl: This conversion yields a list with -1 as the first element, followed by Tcl values corresponding to each union value.
C arrays are represented as Tcl lists (i.e., array elements correspond to Tcl list elements). For example: int x[3]={1,2,3}; is simply represented as {1 2 3}.
Tcl->C: Each element of the Tcl list is converted to the
corresponding array element.
C->Tcl: Elements of the C array are converted to Tcl values and
packed into a Tcl list.