|
|
|
4.2 Using the C callout mechanism
To use the C callout mechanism, you first need to inform Smalltalk about the C
functions that you wish to call. You currently need to do this in two places:
1) you need to establish the mapping between your C function's address and the
name that you wish to refer to it by, and 2) define that function along with
how the argument objects should be mapped to C data types to the Smalltalk
interpreter. As an example, let us use the pre-defined (to GNU Smalltalk)
functions of system and getenv.
First, the mapping between these functions and string names for the functions
needs to be established in `cint.c'. In the function
initCFuncs, the following code appears:
| | extern int system();
extern char *getenv();
defineCFunc("system", system);
defineCFunc("getenv", getenv);
|
Any functions that you will call from Smalltalk must be similarly defined.
Second, we need to define a method that will invoke these C functions and
describe its arguments to the Smalltalk runtime system. Such a method
is automatically generated by calling a method which is available to every
class, defineCFunc:withSelectorArgs:returning:args:. The method
that was used in old versions of GNU Smalltalk,
defineCFunc:withSelectorArgs:forClass:returning:args:, is still
present for backward compatibility, but its use is deprecated and should
be avoided.
Here are the definitions for the two functions system and
getenv (taken from `CFuncs.st')
| | SystemDictionary defineCFunc: 'system'
withSelectorArgs: 'system: aString'
returning: #int
args: #(#string)!
SystemDictionary defineCFunc: 'getenv'
withSelectorArgs: 'getenv: aString'
returning: #string
args: #(#string)!
|
The various keyword arguments are described below.
The arguments are as follows:
SystemDictionary
- This specifies where the new method should be stored. In our case, the
method will be installed in the SystemDictionary, so that we would
invoke it thus:
| | Smalltalk system: 'lpr README' !
|
Again, there is no special significance to which class receives the
method; it could have just as well been Float, but it might look kind
of strange to see:
| | 1701.0 system: 'mail sbb@gnu.org' !
|
defineCFunc: 'system'
- This says that we are defining the C function
system. This name
must be exactly the same as the string passed to
defineCFunc.
withSelectorArgs: 'system: aString'
- This defines how this method will be invoked from Smalltalk. The name
of the method does not have to match the name of the C function; we
could have just as easily defined the selector to be
'rambo: fooFoo';
it's just good practice to define the method with a similar name and
the argument names to reflect the data types that should be passed.
returning: #int
- This defines the C data type that will be returned. It is converted to
the corresponding Smalltalk data type. The set of legal return types
is:
char
- Single C character value
string
- A C char *, converted to a Smalltalk string
stringOut
- A C char *, converted to a Smalltalk string and then freed.
symbol
- A C char *, converted to a Smalltalk symbol
int
- A C int value
uInt
- A C unsigned int value
long
- A C long value
uLong
- A C unsigned long value
double
- A C double, converted to an instance of Float
void
- No returned value
cObject
- An anonymous C pointer; useful to pass back to
some C function later
smalltalk
- An anonymous (to C) Smalltalk object pointer; should
have been passed to C at some point in the past or
created by the program by calling other public
GNU Smalltalk functions (see section 4.4 Manipulating Smalltalk data from C).
ctype
- You can pass an instance of CType or one of its
subclasses (see section 4.3 The C data type manipulation system)
args: #(#string)
- This is an array of symbols that describes the types of the arguments
in order. For example, to specify a call to open(2), the arguments
might look something like:
| | args: #(#string #int #int)
|
The following argument types are supported; see above for details.
unknown
- Smalltalk will make the best conversion that it can guess
for this object; see the mapping table below
boolean
- passed as
char, which is promoted to int
char
- passed as
char, which is promoted to int
string
- passed as
char *
stringOut
- passed as
char *, the contents are expected to be
overwritten with a new C string, and the object that
was passed becomes the new string on return
symbol
- passed as
char *
byteArray
- passed as
char *, even though may contain NUL's
int
- passed as
int
uInt
- passed as
unsigned int
long
- passed as
long
uLong
- passed as
unsigned long
double
- passed as
double
cObject
- C object value passed as
long or void *
smalltalk
- Pass the object pointer to C. The C routine should
treat the value as a pointer to anonymous storage.
This pointer can be returned to Smalltalk at some
later point in time.
variadic
variadicSmalltalk
- an Array is expected, each of the elements of the
array will be converted like an
unknown
parameter if variadic is used, or passed as
a raw object pointer for variadicSmalltalk.
self
selfSmalltalk
- Pass the receiver, converting it to C like an
unknown
parameter if self is used or passing the raw
object pointer for selfSmalltalk. Parameters
passed this way don't map to the message's arguments,
instead they map to the message's receiver.
Table of parameter conversions:
| Declared param type | Object type | C parameter type used |
| boolean | Boolean (True, False) | int |
| byteArray | ByteArray | char * |
| cObject | CObject | void * |
| char | Boolean (True, False) | int |
| char | Character | int (C promotion rule) |
| char | Integer | int |
| double | Float | double (C promotion) |
| int | Boolean (True, False) | int |
| int | Integer | int |
| uInt | Boolean (True, False) | unsigned int |
| uInt | Integer | unsigned int |
| long | Boolean (True, False) | long |
| long | Integer | long |
| uLong | Boolean (True, False) | unsigned long |
| uLong | Integer | unsigned long |
| smalltalk, selfSmalltalk | anything | OOP |
| string | String | char * |
| string | Symbol | char * |
| stringOut | String | char * |
| symbol | Symbol | char * |
| unknown, self | Boolean (True, False) | int |
| unknown, self | ByteArray | char * |
| unknown, self | CObject | void * |
| unknown, self | Character | int |
| unknown, self | Float | double |
| unknown, self | Integer | long |
| unknown, self | String | char * |
| unknown, self | Symbol | char * |
| unknown, self | anything else | OOP |
| variadic | Array | each element is passed according to "unknown" |
| variadicSmalltalk | Array | each element is passed as an OOP |
|