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 not an acronym for anything, as far as I know). 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 thetrue
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. APTR
is avoid *
if supported, or otherwise achar *
.
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 isnil
, 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 along
, you might need to cast it to either achar *
orPTR
.
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 Clong
. Note that Smalltalk integers are always signed and have a bit less of precision with respect to C longs. On 32 bit machines, their precision is 30 bits (if unsigned) or 31 bits (if signed); on 64 bit machines, their precision is 62 bits (if unsigned) or 63 bits (if signed).
This function returns an OOP from a unique identifier returned by
OOPToId
. The OOP will be the same that was passed toOOPToId
only if the original OOP has not been garbage-collected since the call toOOPToId
.
This object returns a Smalltalk
FloatD
which contains the same value as the passeddouble
. Unlike Integers, FloatDs have exactly the same precision as C doubles.
This object returns a Smalltalk
FloatQ
which contains the same value as the passedlong 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 Cint
. That is, the returned OOP is the sole instance of eitherFalse
orTrue
, depending on where the parameter is zero or not.
This object returns a Smalltalk
Character
which represents the same char as the passed Cchar
.
This object returns a Smalltalk
Character
orUnicodeCharacter
which represents the same char as the passed Cwchar_t
.
This method returns the Smalltalk class (i.e. an instance of a subclass of Class) whose name is the given parameter. 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, usecObjectToTypedOOP
.
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 usetypeNameToOOP
.
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.
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.