Next: Smalltalk callin, Previous: C data types, Up: C and Smalltalk
GNU Smalltalk internally maps every object except Integers to a data structure named an OOP (which is short for Ordinary Object Pointer). An OOP is a pointer to an internal data structure; this data structure basically adds a level of indirection in the representation of objects, since it contains
This additional level of indirection makes garbage collection very efficient, since the collector is free to move an object in memory without updating every reference to that object in the heap, thereby keeping the heap fully compact and allowing very fast allocation of new objects. However, it makes C code that wants to deal with objects even more messy than it would be without; if you want some examples, look at the hairy code in GNU Smalltalk that deals with processes.
To shield you as much as possible from the complications of doing object-oriented programming in a non-object-oriented environment like C, GNU Smalltalk provides friendly functions to map between common Smalltalk objects and C types. This way you can simply declare OOP variables and then use these functions to treat their contents like C data.
These functions are passed to a module via the VMProxy
struct, a
pointer to which is passed to the module, as shown in Linking your libraries to the virtual machine. They can be
divided in two groups, those that map from Smalltalk objects to C
data types and those that map from C data types to Smalltalk
objects.
Here are those in the former group (Smalltalk to C); you can see that
they all begin with OOPTo
:
This function assumes that the passed OOP is an Integer and returns the
C signed long
for that integer.
This function returns an unique identifier for the given OOP, valid until the OOP is garbage-collected.
This function assumes that the passed OOP is an Integer or Float and
returns the C double
for that object.
This function assumes that the passed OOP is an Integer or Float and
returns the C long double
for that object.
This function returns a C integer which is true (i.e. != 0
) if
the given OOP is the true
object, false (i.e. == 0
)
otherwise.
This function assumes that the passed OOP is a Character and returns the
C char
for that integer.
This function assumes that the passed OOP is a Character or
UnicodeCharacter and returns the C wchar_t
for that integer.
This function assumes that the passed OOP is a String or ByteArray and
returns a C null-terminated char *
with the same contents. It is
the caller’s responsibility to free the pointer and to handle possible
‘NUL’ characters inside the Smalltalk object.
This function assumes that the passed OOP is a UnicodeString and
returns a C null-terminated wchar_t *
with the same contents. It is
the caller’s responsibility to free the pointer and to handle possible
‘NUL’ characters inside the Smalltalk object.
This function assumes that the passed OOP is a String or ByteArray and
returns a C char *
with the same contents, without
null-terminating it. It is the caller’s responsibility to free the
pointer.
This functions assumes that the passed OOP is a kind of CObject and
returns a C PTR
to the C data pointed to by the object. The
caller should not free the pointer, nor assume anything about its size
and contents, unless it exactly knows what it’s doing. A PTR
is a void *
if supported, or otherwise a char *
.
This functions assumes that the passed OOP is a String, a ByteArray,
a CObject, or a built-in object (nil
, true
, false
,
character, integer). If the OOP is nil
, it answers 0; else the
mapping for each object is exactly the same as for the above functions.
Note that, even though the function is declared as returning a
long
, you might need to cast it to either a char *
or PTR
.
While special care is needed to use the functions above (you will
probably want to know at least the type of the Smalltalk object you’re
converting), the functions below, which convert C data to Smalltalk
objects, are easier to use and also put objects in the incubator so that
they are not swept by a garbage collection (see Incubator). These
functions all end with ToOOP
, except
cObjectToTypedOOP
:
This object returns a Smalltalk Integer
which contains the same value as
the passed C long
.
This object returns a Smalltalk Integer
which contains the same value as
the passed C unsigned long
.
This function returns an OOP from a unique identifier returned by
OOPToId
. The OOP will be the same that was passed to
OOPToId
only if the original OOP has not been garbage-collected
since the call to OOPToId
.
This object returns a Smalltalk FloatD
which contains the same value as
the passed double
. Unlike Integers, FloatDs have exactly the same
precision as C doubles.
This object returns a Smalltalk FloatQ
which contains the same value as
the passed long double
. Unlike Integers, FloatQs have exactly the same
precision as C long doubles.
This object returns a Smalltalk Boolean
which contains the same boolean
value as the passed C int
. That is, the returned OOP is the sole
instance of either False
or True
, depending on where the
parameter is zero or not.
This object returns a Smalltalk Character
which represents the same char
as the passed C char
.
This object returns a Smalltalk Character
or UnicodeCharacter
which represents the same char as the passed C wchar_t
.
This method returns the Smalltalk class (i.e. an instance of a subclass
of Class) whose name is the given parameter. Namespaces are supported;
the parameter must give the complete path to the class starting from the
Smalltalk
dictionary. NULL
is returned if the class is
not found.
This method is slow; you can safely cache its result.
This method returns a String which maps to the given null-terminated C
string, or the builtin object nil
if the parameter points to
address 0 (zero).
This method returns a UnicodeString which maps to the given null-terminated C
wide string, or the builtin object nil
if the parameter points to
address 0 (zero).
This method returns a ByteArray which maps to the bytes that the first
parameters points to; the second parameter gives the size of the
ByteArray. The builtin object nil
is returned if the first
parameter points to address 0 (zero).
This method returns a String which maps to the given null-terminated C
string, or the builtin object nil
if the parameter points to
address 0 (zero).
This method returns a CObject which maps to the given C pointer, or the
builtin object nil
if the parameter points to address 0 (zero).
The returned value has no precise CType assigned. To assign one, use
cObjectToTypedOOP
.
This method returns a CObject which maps to the given C pointer, or the
builtin object nil
if the parameter points to address 0 (zero).
The returned value has the second parameter as its type; to get possible
types you can use typeNameToOOP
.
All this method actually does is evaluating its parameter as Smalltalk code; so you can, for example, use it in any of these ways:
cIntType = typeNameToOOP("CIntType"); myOwnCStructType = typeNameToOOP("MyOwnCStruct type");
This method is primarily used by msgSendf
(see Smalltalk callin),
but it can be useful if you use lower level call-in methods. This method
is slow too; you can safely cache its result.
As said above, the C to Smalltalk layer automatically puts the objects it creates in the incubator which prevents objects from being collected as garbage. A plugin, however, has limited control on the incubator, and the incubator itself is not at all useful when objects should be kept registered for a relatively long time, and whose lives in the registry typically overlap.
To avoid garbage collection of such object, you can use these functions, which access a separate registry:
Puts the given OOP in the registry. If you register an object multiple times, you will need to unregister it the same number of times. You may want to register objects returned by Smalltalk call-ins.
Removes an occurrence of the given OOP from the registry.
Tells the garbage collector that an array of objects must be made part of the root set. The two parameters point indirectly to the base and the top of the array; that is, they are pointers to variables holding the base and the top of the array: having indirect pointers allows you to dynamically change the size of the array and even to relocate it in memory without having to unregister and re-register it every time you modify it. If you register an array multiple times, you will need to unregister it the same number of times.
Removes the array with the given base from the registry.
Next: Smalltalk callin, Previous: C data types, Up: C and Smalltalk