• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /macosx-10.10.1/pyobjc-45/pyobjc/pyobjc-core-2.5.1/Doc/sphinx_build/html/_sources/dev/
1========================================
2How to wrap an Objective-C class library
3========================================
4
5.. :author: Ronald Oussoren
6
7Introduction
8------------
9
10.. warning::
11
12  This document is very dated and needs to be rewritten. The easiest way
13  to wrap a framework that requires more than what is described in
14  `The basics`_ is to copy an existing framework wrapper and adapt that.
15
16  Tool support is currently totally broken.
17
18This document describes how you can wrap on Objective-C class library using
19a Python module or package.  This document assumes that your class library is
20located in a framework.
21
22Wrapping can be pretty easy for most classes, but you may have to write some
23C code for specific methods.
24
25The basics
26----------
27
28The code for loading a framework and exporting its classes is pretty simple:
29
30 .. sourcecode: python
31
32    import objc
33    objc.loadBundle("MyFramework", globals(), 
34       bundle_path=objc.pathForFramework(u'/path/to/MyFramework.framework'))
35    del objc
36
37In general you should not load frameworks this way, but you should write a
38package or module to do this for you (e.g. place this code in
39``MyFramework.py`` or ``MyFramework/__init__.py``.  This makes it possible to 
40``import MyFramework`` which is much more convenient.
41
42If your class library does not require helper functions for some methods this
43is all that is needed.
44
45It is currently necessary to import the wrapper modules for all frameworks that
46are used by your framework.  Not doing this may lead to subtle bugs in other
47parts of the code.  This is a limitation of PyObjC that will be 
48lifted in a future version.
49
50Wrapping global functions and constants
51---------------------------------------
52
53The code above only provides wrappers for Objective-C classes, if the library
54also defines global functions and/or constants you'll have to write an 
55extension module to make these available to Python.
56
57You can use the PyObjC C-API (to be documented) when writing this module.  With
58some luck you can adapt the scripts in ``Scripts/CodeGenerators`` to generate
59this module for you.  These scripts are both very rough and tuned for the Apple
60headers, so YMMV.
61
62Note that we currently do not install the ``pyobjc-api.h`` header, you'll have
63to copy it from the source-tree until we do.  This header is not installed 
64because the interface is not yet stable, please let us know if you want to
65use the API.
66
67Pointer arguments
68-----------------
69
70Methods with pointer arguments (other then arguments that are equivalent to 
71an 'id') require more work.  If the pointer arguments are used to pass a single 
72value to/from a function ('pass-by-reference arguments') you'll just have to 
73provide more specific method signatures.  In other cases you'll have to write
74custom wrappers for these methods.
75
76Check ``Modules/Foundation`` for examples of these custom wrappers.
77
78Pass-by-reference arguments
79...........................
80
81Pass-by-reference arguments can be 'in' (data passed into the function), 
82'out' (data is returned from the function) or 'inout' (data is passed into 
83and then returned from  the function). 
84
85Given the following class interface:
86
87 .. sourcecode: objective-c
88
89   @interface ClassName {}
90
91   -(void)selector:(id*)outArgument withArguments:(NSArray*)data;
92
93   @end
94 
95The compiler will generate a method signature for this method and this can 
96be accessed from Python using the property 'signature' of Objective-C methods. 
97You can also just make up the signature, which is quite easy once you get the
98hang of it.  The signature for this method is 'v@:^@@'.  See `Type Encodings`_
99for the list of valid encoding characters for the Apple Objective-C runtime.
100
101.. _`Type Encodings`: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html#//apple_ref/doc/uid/TP40008048-CH100-SW1
102
103Let's say the first argument is an output parameter.  Output parameters are 
104denoted in the signature string using the character 'o' before the actual
105argument signature.  The 'correct' signature for method is therefore 'v@:o^@@'.
106The following code tells the bridge about this better method signature:
107
108 .. sourcecode: python
109
110   import objc
111   objc.setSignatureForSelector("ClassName", "selector:withArguments:",
112   	"v@:o^@:@")
113
114To annotate method signatures you'll have to add a single character before all
115'^' characters in the signature of a method.  The characters are:
116
117- output parameter: o
118
119- input parameter: n
120
121- input-output parameter: N
122
123***NOTE:*** The bridge currently supports two other ways to describe metadata,
124which aren't properly documented at the moment.
125
126special wrappers
127................
128
129If the method has pointer arguments that are not pass-by-reference arguments,
130or if the default method wrappers are not suitable for other reasons, you'll
131have to write custom wrappers.  For every custom wrapper you'll have to write
132three functions: 1 to call the method from Python, 1 to call the superclass
133implementation of the method from Python and 1 to call a Python implementation
134of the method from Objective-C.
135
136You also must write a custom wrapper when the method has a variable number
137of arguments.  It is often advisable to documented varargs method as 
138unsupported, or to support them only using a fixed number of arguments.
139
140For now it is best to check the source code for the wrappers for the Cocoa 
141class library for more information.  We'll add documentation for this in the
142future.
143
144protocols
145.........
146
147If the framework defines any (informal) protocols you should add 
148``objc.informal_protocol`` objects for those protocols to your module.  These
149can be defined in a submodule, as long as you arrange for that module to be
150loaded whenever someone imports your package.
151