% Copyright (c) 1996 by Lele Gaifax.  All Rights Reserved
%
% This file is part of the PyObjC package.
%
% $RCSfile: libObjC.tex,v $
% $Revision: 1.1.1.7 $
% $Date: 1996/11/14 01:50:00 $
%
% Created Mon Sep 20 11:47:37 1996.
%

\section{Built-in Module \sectcode{ObjC}}
\bimodindex{ObjC}
\renewcommand{\indexsubitem}{(in module ObjC)}

The \code{ObjC} module furnishes the following functions:

\begin{funcdesc}{make\_pointer}{integer-value}
Build and return a new \code{ObjCPointer} object, containing a pointer
to void with value \var{integer-value}. \emph{You must know what you
are doing}, since misusing such objects may crash your
application.
This method should be used when a pointer argument is used as some
sort of a flag from the Objective-C method.
\end{funcdesc}

\begin{funcdesc}{list\_classes}{}
Build and return the list of available Objective-C classes by quering
its runtime.
\end{funcdesc}

\begin{funcdesc}{load\_object\_files}{list\_of\_object\_filenames}
Try to dynamically load each object file in
\var{list\_of\_object\_filenames}. They may actually be object files, or
libraries of such files.
\end{funcdesc}

\begin{funcdesc}{lookup\_class}{objc\_class\_name}
Locate the given Objective-C \var{objc\_class\_name}, and if known to
the runtime return a ObjCObject wrapper around it.
\end{funcdesc}

An alternative, and maybe cleaner, way to access to the Objective-C
classes is by using the \var{.runtime} member of the module.

\begin{datadesc}{runtime}
This member is a ObjCRuntime object that wraps the Objective-C runtime
in such a way that to request a particular class you simply ask it as
a member in this way:

\begin{verbatim}
>>> import ObjC
>>> Object = ObjC.runtime.Object
\end{verbatim}
\end{datadesc}

The module provides the following others data members:

\begin{datadesc}{streams}
This is the automatically imported ObjCStreams module.
\end{datadesc}

\begin{excdesc}{error}
This is the exception that gets raised upon operation failure, such as
invalid arguments, unknown selectors and so on. The exception argument
is a string describing the reason of the failure.
\end{excdesc}

\begin{datadesc}{__version__}
The version of the module, as a floating point number. This manual
documents version 0.47. % XXX update this before release.
\end{datadesc}

\subsection{ObjCRuntime objects}
\renewcommand{\indexsubitem}{(ObjCRuntime method)}

This object responds to these methods:

\begin{funcdesc}{load\_object\_files}{list\_of\_object\_filenames}
Try to dynamically load each object file in
\var{list\_of\_object\_filenames}. They may actually be object files, or
libraries of such files. A \code{ObjC.error} exception is raised on failure.
\end{funcdesc}

\begin{funcdesc}{lookup\_class}{objc\_class\_name}
Locate the given Objective-C \var{objc\_class\_name}, and if known to
the runtime return a ObjCObject wrapper around it. This should be
superceded by ``.\_\_dict\_\_.keys()''. A \code{ObjC.error} exception
is raised if the class does not exist.
\end{funcdesc}

In every aspects, these two functions are merely aliases of the
module's functions with the same name.

\begin{funcdesc}{sel\_is\_mapped}{selectorName}
Returns \code{True} if the selector \var{selectorName} is known to the
runtime, \code{False} otherwise.
\end{funcdesc}

This object carries the following data members:

\begin{datadesc}{kind}
This tells you for which runtime the module was compiled for, that may
be ``NeXT'' if it is using the native NeXT's runtime, or ``GNU'' when
using the GNU Objective-C runtime distribuited with GNU GCC.
\end{datadesc}

\begin{datadesc}{__dict__}
This is a dictionary of all known classes.
\end{datadesc}

\begin{datadesc}{__members__}
The list of data members of this object.
\end{datadesc}

but you can ask for an Objective-C class using the \code{getattr()}
function or with the ``.ClassName'' syntax too.


\subsection{ObjCObject objects}
\renewcommand{\indexsubitem}{(ObjCObject method)}

From the Python point of view, you access Objective-C objects (both
classes and instances) using a Python wrapper around them,
ObjCObject. It is responsible of forwarding any unknown method you
execute on it to the Objective-C object it is carrying.

ObjCObject objects have the following methods.

\begin{funcdesc}{isClass}{}
Return \var{True} if the enclosed Objective-C object is actually a
class, \var{False} otherwise.
\end{funcdesc}

\begin{funcdesc}{isInstance}{}
Return \var{True} if the enclosed Objective-C object is actually an
instance, \var{False} otherwise.
\end{funcdesc}

\begin{funcdesc}{Class}{}
Since the word ``class'' is a reserved keyword in Python and cannot be
used as a method name, this function returns the equivalent of the
Objective-C expression ``[obj class]''.
\end{funcdesc}


To send a message to an Objective-C object you use the same syntax as
for any other Python object:

\begin{verbatim}
>>> import ObjC
>>> List = ObjC.runtime.List
>>> list = List()
>>> Object = ObjC.runtime.Object
>>> instance = Object()
>>> list.addObject__ (instance)
\end{verbatim}

% XXX fix whenever we select the alternative syntax for ObjC methods
% mapping.

Due to the different calling syntax though the Objective-C selectors
name change slightly: the expression ``[obj someMethod:argA
with:argB]'' becomes ``obj.someMethod\_\_with\_\_ (argA, argB)'' once
coded in Python. The rule to follow is very simple: take the {\em
concise} notation of the selector (the example above gives
``someMethod:with:'') and replace every colon (':') character with a
double underscore ('\_\_'), then feed the arguments as usual. As you may
notice, the name of selectors without arguments does not change at all.

An alternative translation scheme was introduced with version 0.45 of the
module: first replace every underscore in the name with a triple one
('\_\_\_'), then replace every colon with a single underscore. Since
underscores are not common in Objective-C method names, this gives
shorter names. 

\emph{Since allowing this double syntax introduces a little speed
penality, I plan to remove one of the alternatives in the final 1.0
release.} 

The notation ``list.addObject\_\_'' does actually return a
\code{ObjCMethod} instance, described below, that you may cache
as any other method. For example:

\begin{verbatim}
>>> import ObjC
>>> List = ObjC.runtime.List
>>> list_alloc = List.alloc
>>> instance = list_alloc().init()
\end{verbatim}

When an ObjCObject represent a Objective-C class, you can ``call'' it
as you normally do with Python classes: it is a shortcut for a longer
``.alloc().init()''. You can pass initialization arguments to the
call: if the Objective-C class instance responds to a method called
``init:::...'' that method is called feeding it the arguments as
usual. Alternatively, you may specify the right selector to be used to
initialize the object by using the \code{init} keyword parameter, in
this way:

\begin{verbatim}
>>> import ObjC
>>> List = ObjC.runtime.List
>>> list = List(10, init='initCount:')
\end{verbatim}


If the wrapped Objective-C object implements the methods
\code{-length} (or \code{-count}) and \code{-objectAt:} (or
\code{-objectAtIndex:}) than it's possible to treat it as any other
sequence object, thus giving:

\begin{verbatim}
>>> list = ObjC.runtime.List()
>>> list.addObject__ ('spam')
>>> list.addObject__ (1)
>>> list.addObject__ ('liter')
>>> list.addObject__ ('please)
>>> print list.count()
4
>>> print list.capacity()
7
>>> print list[:]
['spam', 1, 'liter', 'please']
>>> print list+list
['spam', 1, 'liter', 'please', 'spam', 1, 'liter', 'please']
>>> print list*3
['spam', 1, 'liter', 'please', 'spam', 1, 'liter', 'please',
'spam', 1, 'liter', 'please']
>>> for i in list: print i
...
spam
1
liter
please
\end{verbatim}

Otherwise, if it implements the methods
\code{-length} (or \code{-count}) and \code{-valueForKey:} (or
\code{-objectForKey:}) than it's possible to treat it as any other
mapping object.

\subsection{ObjCMethod objects}
\renewcommand{\indexsubitem}{(ObjCMethod method)}

An ObjCMethod instance is returned when you ask to an ObjCObject a
particular selector. By ``calling'' it, you execute the associated
Objective-C method. It knows about the number of arguments the
selector accepts, and their type, so that it's able to convert a
Python value to a suitable C value, and viceversa. For example, when a
selector takes a \code{struct} value, you actually feed it a Python
tuple object, then the ObjCMethod will convert that tuple to the needed
C struct value; if it returns a \code{char *} value, you actually
receive a standard Python string object. The same translation happens
for C arrays. Other types get translated as you'd expect, except for
\code{char} values, that are converted to integers\footnote{In
Objective-C it's a common pratice to use \code{BOOL} values and in
some implementation this type is an alias for \code{unsigned char}:
``if obj.isClass()'' seems more natural than ``if ord (objc.isClass())
== 1''}, although single-char strings are accepted as arguments. When
a selector is expected, you can give it both as its concise string
representation or by passing an ObjCMethod instance of it.

To explain better, given the Objective-C declarations:

\begin{verbatim}
typedef struct _point { float x,y } Point;
typedef struct _size { float w,h } Size;
typedef struct _rect { Point origin; Size size } Rect;

@interface Square : Object
{
  Rect frame;
}

- initWithFrame:(Rect) r;
- (void) getFrame:(Rect *) r;
- (void) perform:(SEL) sel;
- (void) show;

@end
\end{verbatim}

to pass the \var{r} argument to \code{initWithFrame:} you must build a
tuple of two items, the first to be a tuple with two elements for the
\var{origin}, with values for \var{x} and \var{y} in it; the second
for the \var{size} slot, another tuple containing values for \var{w}
and \var{h}. This gives:

\begin{verbatim}
>>> import ObjC
>>> myroom = ObjC.runtime.Square.alloc()
>>> myroom.initWithFrame__ ( (0.0, 0.0), (12.3, 8.1) )
>>> ...
>>> # these are equivalent
>>> myroom.perform__ ("show")
>>> myroom.perform__ (myroom.show)
\end{verbatim}

A little complication arises with methods that take a
\dfn{pass-by-reference} argument: usually such arguments are used when
the selector wants to return more than one value, for example a status
of operation and an actual result value. In this case the method may
modify its arguments; since in Python there is no notion of
pass-by-reference argument syntax, you must use a different way.

\begin{funcdesc}{pack_argument}{argn\optional{, value}}
This method builds a \dfn{packed} representation of the given Python
\var{value} suitable to be feeded as the \var{argn}-th
argument of the method, and returns an ObjCPointer object as its
container. If \var{value} is not given, the content of the packed
value will not be initialized.
\end{funcdesc}

\begin{funcdesc}{unpack_argument}{argn, packedValue}
This method takes the packed value in \var{packedValue} and unpacks it
accordingly to the type of the \var{argn}-th argument of the method,
thus returning the Python representation of it. \var{packedValue} may
be coming from a \code{struct.pack()}, ie a string object, or from a
\code{.pack\_argument()}, ie an ObjCPointer object.
\end{funcdesc}

Given the Objective-C declaration above, to get the \var{frame} of a
\code{Square} object you should use

\begin{verbatim}
>>> ...
>>> framep = myroom.getFrame__.pack_argument (0)
>>> myroom.getFrame__ (framep)
>>> itsFrame = myroom.getFrame__.unpack_argument (0, framep)
>>> # which by the way is the same as
>>> itsFrame = framep.unpack()
\end{verbatim}

Note that ObjCMethod will silently slurp the argument if passed in the
normal way, ie not in packed form, but you won't be able to fetch its
modified value, that is

\begin{verbatim}
>>> ...
>>> frame = ( (0.0, 0.0), (0.0, 0.0) )
>>> myroom.getFrame__ (frame)
>>> print frame
>>> ((0.0,0.0),(0.0,0.0))
\end{verbatim}

An ObjCMethod has these data members:

\begin{datadesc}{name}
This is the name of the ObjC selector this object is wrapping.
\end{datadesc}

\begin{datadesc}{__members__}
The list of data members of this object.
\end{datadesc}


\subsection{ObjCPointer objects}
\renewcommand{\indexsubitem}{(ObjCPointer method)}

When a Objective-C method returns a pointer to something, this value
gets encoded in a ObjCPointer instance, that you can feed as argument
of another method expecting an equivalent type.

This kind of objects make it easier to access their content: as a
variant of the \code{.unpack\_argument()} described above, they
provide the following method.

\begin{funcdesc}{unpack}{}
This method takes the content of the pointed value and unpacks it
accordingly to its type, then returns the Python representation of it.
\end{funcdesc}

Each ObjCPointer carries these data members:

\begin{datadesc}{type}
A string object containing the type of the pointed value.
\end{datadesc}

\begin{datadesc}{pointerAsInteger}
An integer representation of the pointer itself.
\end{datadesc}

\begin{datadesc}{__members__}
The list of data members of this object.
\end{datadesc}


\subsection{Objective-C encoding}

The Objective-C language has a compiler directive, \dfn{@encode}, that
when given a type specification returns a string encoding that type.
The type can be a basic type such as an int, a pointer, a tagged
structure or union, or a class name -- anything, in fact, that can be
used as an argument to the C \code{sizeof()} operator.

For example:
\begin{verbatim}
char *e1 = @encode(int **);
	=> ^^i
char *e2 = @encode(float[12]);
	=> [12f]
char *e3 = @encode(PyStringObject *);
	=> ^{?=i^{_typeobject}il[1c]}
\end{verbatim}

The ObjC module tries to hide as much as possible these details, but
nevertheless you may find usefull to understand the mechanism: when
you pass a wrong argument to an ObjC message, the exception raised
contains the @encoded description of the expected type for that
argument, and using the information below you should be able to
correctly construct the needed value.

The table below lists the characters used by this mechanism, with
their meanings. The third column tells how the particular item type
matches with the Python objects. As pointed out above, you can
indifferently pass an integer or a string for an argument of type
\code{char}, but the module translates such values to integers when
they are returned by a method.

\begin{tableiii}{|c|l|c|}{code}{Code}{Meaning}{Python Equivalent}
\lineiii{c}{A char}{PyIntObject or PyStringObject}
\lineiii{i}{An int}{PyIntObject}
\lineiii{s}{A short}{PyIntObject}
\lineiii{l}{A long}{PyIntObject}
\lineiii{C}{An unsigned char}{PyIntObject or PyStringObject}
\lineiii{I}{An unsigned int}{PyIntObject}
\lineiii{S}{An unsigned short}{PyIntObject}
\lineiii{L}{An unsigned long}{PyIntObject}
\lineiii{f}{A float}{PyFloatObject or PyIntObject}
\lineiii{d}{A double}{PyFloatObject or PyIntObject}
\lineiii{v}{A void}{}
\lineiii{*}{A character string (char *)}{PyStringObject}
\lineiii{@}{An object (id)}{ObjCObject}
\lineiii{\#}{A class object (Class)}{ObjCObject}
\lineiii{:}{A method selector (SEL)}{ObjCMethod or PyStringObject}
\lineiii{[...]}{An array}{PyTupleObject}
\lineiii{\{...\}}{A structure}{PyTupleObject}
\lineiii{(...)}{A union}{ObjCPointer or PyStringObject}
\lineiii{bnum}{A bitfield of num bits}{not handled}
\lineiii{\^type}{A pointer to type}{value for type}
\lineiii{?}{An unknown type}{}
\end{tableiii}

The type specification for an array is enclosed within square
brackets; the number of elements in the array is specified immediately
after the open bracket, before the array type.  For example, an array
of 12 pointers to \code{floats} would be encoded as:

\begin{verbatim}
[12^f]
\end{verbatim}

Structures are specified within braces, and unions within parentheses.
The structure tag is listed first, followed by an equal sign and the
codes for the fields of the structure listed in sequence.  For
example, this structure,

\begin{verbatim}
typedef struct example
{
  id anObject;
  char *aString;
  int anInt;
} Example;
\end{verbatim}

would be encoded like this:

\begin{verbatim}
{example=@*i}
\end{verbatim}

The same encoding results whether the defined type name (Example) or
the structure tag (example) is passed to @encode().  The encoding for
a structure pointer carries the same amount of information about the
structure's fields:

\begin{verbatim}
^{example=@*i}
\end{verbatim}

However, another level of indirection removes the internal type
specification:

\begin{verbatim}
^^{example}
\end{verbatim}

Internally, the module uses two functions, \code{pythonify_c_value()}
and \code{depythonify_c_value()} to translate a C value into the
corresponding Python object and viceversa. Eventually, in the future,
these functions will be moved into an indipendent module, so that they
may replace the \code{struct} module's functionalities.

%% Local Variables:
%% change-log-default-name:"../ChangeLog.PyObjC"
%% End:

