|
|
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 |
|