| 1 | <html> |
| 2 | <head> |
| 3 | <title>Module Pycaml</title> |
| 4 | </head> |
| 5 | <body> |
| 6 | <table border=0 width="100%"><tr><td bgcolor="#c0c0c0"> |
| 7 | <h1>Pycaml</h1> |
| 8 | </td></tr></table> |
| 9 | <p> |
| 10 | <h2>What is Pycaml</h2> |
| 11 | A library written by <a href=mailto:arty@users.sourceforge.net> |
| 12 | arty@users.sourceforge.net</a> which follows the Python/C API as |
| 13 | closely as possible, while |
| 14 | providing equivalent functionality for objective caml. This is built |
| 15 | against python 2.x and Ocaml 3.04.<p> It is intended to allow users to |
| 16 | build native ocaml libraries and use them from python, and alternately, |
| 17 | in order to allow ocaml users to benefit from linkable libraries provided |
| 18 | for python.<p> |
| 19 | I created this library in order to take advantage of python binding for |
| 20 | certain native libraries from ocaml. While it is true that I could have |
| 21 | written new interfaces specifically for ocaml, the python interface is |
| 22 | sufficient for my needs, and this project was easier.<p> |
| 23 | |
| 24 | <b>Note:</b> Unfortunately, the symbol <tt>init_exceptions</tt> exists in |
| 25 | both compiled ocaml code, and the python runtime. In order to proceed, you |
| 26 | must rename this symbol either in the ocaml distribution (in byterun/fail.c, |
| 27 | and byterun/startup.c), or in the python distribution, and rebuild the |
| 28 | software appropriately.<p> |
| 29 | |
| 30 | Please edit the <tt>Makefile</tt> to put in your system's libraries used for |
| 31 | compiling programs embedded with python. This library compiles on most |
| 32 | linux boxes without modification. The python interpreter is used to determine |
| 33 | the path to the python library and must be in your path when you run make. |
| 34 | <p> |
| 35 | |
| 36 | <b>Get the distribution here:</b><a href=pycaml.tar.gz>pycaml.tar.gz</a><p> |
| 37 | |
| 38 | Because these are made to closely mirror the python API, the user should |
| 39 | become familiar with the python API.<p> |
| 40 | Given Ocaml parameter passing convention, it was convenient to pass multiple |
| 41 | arguments as members of a tuple, but single arguments without. Consequently, |
| 42 | functions with arity 1, such as pytuple_new are called as<p> |
| 43 | <pre> |
| 44 | pytuple_new 3 ;; |
| 45 | </pre><p> |
| 46 | And functions with more arguments are called as<p> |
| 47 | <pre> |
| 48 | pydict_getitemstring (dict,"keystring") ;; |
| 49 | </pre> |
| 50 | |
| 51 | <h2>Module Pycaml</h2> |
| 52 | |
| 53 | <h3>Visible Types</h3> |
| 54 | |
| 55 | <table border=0> |
| 56 | <tr bgcolor="#c0c0c0"><td>type</td><td width="100%">pyobject</td></tr> |
| 57 | <tr><td colspan=2> |
| 58 | The abstract type of python objects. |
| 59 | </td></tr> |
| 60 | <tr bgcolor="#c0c0c0"><td>type</td><td>pyobject_type =</td></tr> |
| 61 | <tr><td align=right></td><td>TupleType</td></tr> |
| 62 | <tr><td align=right>|</td><td>StringType</td></tr> |
| 63 | <tr><td align=right>|</td><td>IntType</td></tr> |
| 64 | <tr><td align=right>|</td><td>FloatType</td></tr> |
| 65 | <tr><td align=right>|</td><td>ListType</td></tr> |
| 66 | <tr><td align=right>|</td><td>NoneType</td></tr> |
| 67 | <tr><td align=right>|</td><td>CallableType</td></tr> |
| 68 | <tr><td align=right>|</td><td>ModuleType</td></tr> |
| 69 | <tr><td align=right>|</td><td>ClassType</td></tr> |
| 70 | <tr><td align=right>|</td><td>TypeType</td></tr> |
| 71 | <tr><td align=right>|</td><td>OtherType</td></tr> |
| 72 | <tr><td colspan=2> |
| 73 | The type representing the range of types available to python programs. |
| 74 | Values of this type are provided by the pytype function, and identify the |
| 75 | python type of opaque pyobject objects. |
| 76 | </td></tr></table> |
| 77 | |
| 78 | <h3>Supported Functions from the Python/C API</h3> |
| 79 | In each case, the signature of the function is unchanged from the Python/C |
| 80 | API except for the case of 'out' pointer to pointer parameters; |
| 81 | in the case of a single return, the returned value is copied, otherwise, |
| 82 | a tuple is created with copies of all output parameters. In the case of |
| 83 | zero parameter, or void return, unit is used.<p> |
| 84 | In python API functions that take a FILE *, an int file descriptor is used |
| 85 | instead such as those returned by the Unix library.<p> |
| 86 | |
| 87 | <h4>fun unit -> unit</h4> |
| 88 | py_initialize, py_finalize, pyerr_print, pyerr_clear, pyimport_cleanup |
| 89 | <h4>fun int -> unit</h4> |
| 90 | py_exit, pyerr_printex |
| 91 | <h4>fun string -> unit</h4> |
| 92 | py_setprogramname, py_setpythonhome |
| 93 | <h4>fun unit -> int</h4> |
| 94 | py_isinitialized, pyeval_getrestricted |
| 95 | <h4>fun string -> int</h4> |
| 96 | pyrun_simplestring, pyimport_importfrozenmodule, |
| 97 | <h4>fun (int * string) -> int</h4> |
| 98 | pyrun_anyfile, pyrun_simplefile, pyrun_interactiveone, pyrun_interactiveloop, |
| 99 | py_fdisinteractive |
| 100 | <h4>fun (int * string * int) -> int</h4> |
| 101 | pyrun_anyfileex, pyrun_simplefileex |
| 102 | <h4>fun unit -> string</h4> |
| 103 | py_getprogramname, py_getpthonhome, py_getprogramfullpath, py_getprefix, |
| 104 | py_getexecprefix, py_getpath, py_getversion, py_getplatform, py_getcopyright, |
| 105 | py_getcompiler, py_getbuildinfo |
| 106 | <h4>fun (string * int * pyobject * pyobject) -> pyobject</h4> |
| 107 | pyrun_string |
| 108 | <h4>fun (int * string * int * pyobject * pyobject) -> pyobject</h4> |
| 109 | pyrun_file |
| 110 | <h4>fun (int * string * int * pyobject * pyobject * int) -> pyobject</h4> |
| 111 | pyrun_fileex |
| 112 | <h4>fun (string * string * int) -> pyobject</h4> |
| 113 | py_compilestring |
| 114 | <h4>fun (pyobject * int * int) -> int</h4> |
| 115 | pyobject_print, pytuple_getslice, pysequence_getslice</h4> |
| 116 | <h4>fun pyobject -> pyobject</h4> |
| 117 | pyobject_repr, pyobject_str, pyobject_unicode, pydict_keys, pydict_values, |
| 118 | pydict_items, pydict_copy, pymodule_getdict, pymethod_function, pymethod_self, |
| 119 | pymethod_class, pymodule_getdict, pyimport_reloadmodule, pyobject_type, |
| 120 | pynumber_negative, pynumber_positive, pynumber_absolute, pynumber_invert, |
| 121 | pynumber_int, pynumber_long, pynumber_float, pysequence_tuple, pysequence_list |
| 122 | <h4>fun (pyobject * pyobject * int) -> pyobject</h4> |
| 123 | pyobject_richcompare |
| 124 | <h4>fun (pyobject * string) -> pyobject</h4> |
| 125 | pyobject_getattrstring, pydict_getitemstring, pysequence_fast, |
| 126 | pymapping_haskeystring, pymapping_getitemstring |
| 127 | <h4>fun (pyobject * pyobject) -> pyobject</h4> |
| 128 | pyobject_getattr, pystring_format, pydict_getitem, pyinstance_newraw, |
| 129 | pyeval_callobject, pyobject_getitem, pyobject_delitem, pynumber_add, |
| 130 | pynumber_subtract, pynumber_multiply, pynumber_divide, pynumber_remainder, |
| 131 | pynumber_divmod, pynumber_lshift, pynumber_rshift, pynumber_and, pynumber_xor, |
| 132 | pynumber_or, pynumber_inplaceadd, pynumber_inplacesubtract, pynumber_inplacemultiply, pynumber_inplacedivide, pynumber_inplaceremainder, pynumber_inplacelshift, pynumber_inplacershift, pynumber_inplaceand, pynumber_inplacexor, pynumber_inplaceor, pysequence_concat, pysequence_inplaceconcat |
| 133 | <h4>fun pyobject -> int</h4> |
| 134 | pyobject_istrue, pyobject_not, pycalable_check, pystring_size, pydict_size, |
| 135 | pytuple_new, pyerr_exceptionmatches, pyobject_size, pynumber_check, |
| 136 | pysequence_check, pysequence_size, pysequence_length, pymapping_check, |
| 137 | pymapping_size, pymapping_length, pyint_asint |
| 138 | <h4>fun (pyobject * pyobject) -> int</h4> |
| 139 | pyobject_compare, pyobject_hasattr, pydict_delitem, |
| 140 | pyerr_givenexceptionmatches, pysequence_count, pysequence_contains, |
| 141 | pysequence_in, pysequence_index, pymapping_haskey |
| 142 | <h4>fun (pyobject * pyobject * int) -> int</h4> |
| 143 | pyobject_richcomparebool, pysequence_delitem |
| 144 | <h4>fun (pyobject * string * pyobject) -> int</h4> |
| 145 | pyobject_setattrstring, pydict_setitemstring |
| 146 | <h4>fun (pyobject * string) -> int</h4> |
| 147 | pyobject_hasattrstring, pydict_delitemstring, pysequence_inplacerepeat |
| 148 | <h4>fun (pyobject * pyobject) -> (pyobject * pyobject)</h4> |
| 149 | pynumber_coerce, pynumber_coerceex |
| 150 | <h4>fun (pyobject * pyobject * pyobject) -> int</h4> |
| 151 | pyobject_setattr, pydict_setitem, pyobject_setitem |
| 152 | <h4>fun pyobject -> int64</h4> |
| 153 | pyobject_hash, pyint_aslong |
| 154 | <h4>fun pyobject -> string</h4> |
| 155 | pystring_asstring, pymodule_getname, pymodule_getfilename |
| 156 | <h4>fun (pyobject * pyobject) -> pyobject</h4> |
| 157 | pystring_concat, pystring_concatanddel |
| 158 | <h4>fun string -> pyobject</h4> |
| 159 | pystring_fromstring, pymodule_new, pyimport_addmodule, pyimport_importmodule, |
| 160 | pyimport_import |
| 161 | <h4>fun unit -> pyobject</h4> |
| 162 | pydict_new, pyerr_occurred, pyimport_getmoduledict, pyeval_getbuiltins, |
| 163 | pyeval_getglobals, pyeval_getlocals, pyeval_getframe |
| 164 | <h4>fun pyobject -> unit</h4> |
| 165 | pydict_clear, pyerr_setnone |
| 166 | <h4>fun (pyobject * int) -> (pyobject * pyobject * int)</h4> |
| 167 | pydict_next |
| 168 | <h4>fun int64 -> pyobject</h4> |
| 169 | pyint_fromlong |
| 170 | <h4>fun unit -> int64</h4> |
| 171 | pyint_getmax |
| 172 | <h4>fun float -> pyobject</h4> |
| 173 | pyfloat_fromdouble |
| 174 | <h4>fun pyobject -> float</h4> |
| 175 | pyfloat_asdouble |
| 176 | <h4>fun int -> pyobject</h4> |
| 177 | pytuple_new, pyint_fromint |
| 178 | <h4>fun (pyobject * int) -> pyobject</h4> |
| 179 | pytuple_getitem, pysequence_repeat, pysequence_getitem |
| 180 | <h4>fun (pyobject * int * pyobject) -> int</h4> |
| 181 | pytuple_setitem, pysequence_setitem, pymapping_setitem |
| 182 | <h4>fun (pyobject * pyobject * pyobject) -> pyobject</h4> |
| 183 | pyslice_new, pyclass_new, pyinstance_new, pymethod_new, |
| 184 | pyeval_callobjectwithkeywords, pynumber_power, pynumber_inplacepower |
| 185 | <h4>fun (pyobject * int) -> (int * int * int)</h4> |
| 186 | pyslice_getindices |
| 187 | <h4>fun (int * int * int * int) -> pyobject</h4> |
| 188 | pyrange_new |
| 189 | <h4>fun (pyobject * pyobject) -> unit</h4> |
| 190 | pyerr_setobject |
| 191 | <h4>fun (pyobject * string) -> unit</h4> |
| 192 | pyerr_setstring |
| 193 | <h4>fun (pyobject * pyobject * pyobject) -> (pyobject * pyobject * pyobject)</h4> |
| 194 | pyerr_fetch, pyerr_normalizeexception |
| 195 | <h4>fun (pyobject * pyobject * pyobject) -> unit</h4> |
| 196 | pyerr_restore |
| 197 | <h4>fun (pyobject * string) -> pyobject</h4> |
| 198 | pyimport_execcodemodule |
| 199 | <h4>fun (string * pyobject * string) -> pyobject</h4> |
| 200 | pyimport_execcodemoduleex |
| 201 | <h4>fun (string * pyobject * pyobject * pyobject) -> pyobject</h4> |
| 202 | pyimport_importmoduleex |
| 203 | <h4>fun pyobject -> string</h4> |
| 204 | pyobject_ascharbuffer, pyobject_asreadbuffer, pyobject_aswritebuffer |
| 205 | <h4>fun (pyobject * int * int * pyobject) -> int</h4> |
| 206 | pysequence_setslice |
| 207 | <h4>fun (pyobject * int * int) -> int</h4> |
| 208 | pysequence_delslice |
| 209 | |
| 210 | <h3>Unique Functions Needed for Ocaml</h3> |
| 211 | In addition to the functions in the usual library, several new functions are |
| 212 | provided which give specific support for ocaml.<p> |
| 213 | |
| 214 | <table border=0 width=100%> |
| 215 | <tr bgcolor="#c0c0c0"> |
| 216 | <td><b>pytuple_toarray</b></td> |
| 217 | <td>pyobject -> pyobject array</td></tr> |
| 218 | <tr><td colspan=2> |
| 219 | Convert a python tuple to an ocaml array containing the same items. |
| 220 | </td></tr> |
| 221 | <tr bgcolor="#c0c0c0"> |
| 222 | <td><b>pywrap_closure</b></td><td>(pyobject -> pyobject) -> pyobject</td></tr> |
| 223 | <tr><td colspan=2> |
| 224 | Create a python callable object from a closure. The closure receives the |
| 225 | argument tuple from the invocation and returns a pyobject. |
| 226 | </td></tr> |
| 227 | <tr bgcolor="#c0c0c0"> |
| 228 | <td><b>pywrap_value</b></td><td>'a -> pyobject</td></tr> |
| 229 | <tr><td colspan=2> |
| 230 | Create a simple void * style wrapping around an ocaml object. The object |
| 231 | may be retrieved with <tt>pyunwrap_value : pyobject -> 'a</tt>. Use this |
| 232 | to enclose an ocaml data structure in python to be used later. |
| 233 | </td></tr> |
| 234 | <tr bgcolor="#c0c0c0"> |
| 235 | <td><b>pynull</b></td><td>unit -> pyobject</td></tr> |
| 236 | <tr><td colspan=2> |
| 237 | Generate the null PyObject * and return it. This may sound dangerous, but |
| 238 | it is used by library calls to indicate errors to the python system. |
| 239 | </td></tr> |
| 240 | <tr bgcolor="#c0c0c0"> |
| 241 | <td><b>pynone</b></td><td>unit -> pyobject</td></tr> |
| 242 | <tr><td colspan=2> |
| 243 | Generate a reference to the Py_None object. |
| 244 | </td></tr> |
| 245 | <tr bgcolor="#c0c0c0"> |
| 246 | <td><b>pytuple_fromarray</b></td> |
| 247 | <td>pyobject array -> pyobject</td></tr> |
| 248 | <tr><td colspan=2> |
| 249 | Create a pytuple (as would be used for a function call) from the given |
| 250 | array. This may be used to implement varargs calls on python functions, |
| 251 | and for other purposes. |
| 252 | </td></tr> |
| 253 | <tr bgcolor="#c0c0c0"> |
| 254 | <td><b>pytuple_empty</b></td> |
| 255 | <td>pyobject array -> pyobject</td></tr> |
| 256 | <tr><td colspan=2> |
| 257 | Shortcut for <tt>pytuple_new 0</tt> |
| 258 | </td></tr> |
| 259 | |
| 260 | <tr bgcolor="#c0c0c0"> |
| 261 | <td><b>pytuple_fromsingle</b></td> |
| 262 | <td>pyobject -> pyobject</tt></td></tr> |
| 263 | <tr><td colspan=2> |
| 264 | Create a tuple with the single given object inside. Use this to create |
| 265 | single element tuples as for a function call with one argument. |
| 266 | </td></tr> |
| 267 | |
| 268 | <tr bgcolor="#c0c0c0"> |
| 269 | <td><b>pytuple<i>1-5</i></b></td> |
| 270 | <td>(pyobject * ...) -> pyobject</tt></td></tr> |
| 271 | <tr><td colspan=2> |
| 272 | Create a python tuple that has the same contents as the given ocaml tuple. |
| 273 | </td></tr> |
| 274 | |
| 275 | <tr bgcolor="#c0c0c0"> |
| 276 | <td><b>pytype</b></td> |
| 277 | <td>pyobject -> pyobject_type</tt></td></tr> |
| 278 | <tr><td colspan=2> |
| 279 | Determine roughly which type family the given value belongs to. For example, |
| 280 | <tt>pytype (pystring_fromstring "hi")</tt> yields <tt>StringType</tt>. |
| 281 | </td></tr> |
| 282 | </table> |
| 283 | |
| 284 | <h3>Sample Application</h3> |
| 285 | This is the sample application that I developed the library with. It |
| 286 | illustrates a python function call, as well as a call back into ocaml. |
| 287 | The first form is used in cases where python libraries are to be used |
| 288 | from ocaml, and the second would be used to produce native libraries in |
| 289 | ocaml.<p> |
| 290 | |
| 291 | <pre> |
| 292 | open Pycaml ;; |
| 293 | |
| 294 | let colorsys = pyimport_importmodule "colorsys" |
| 295 | let dict = pymodule_getdict colorsys |
| 296 | |
| 297 | let triplet = pytuple3 (pyfloat_fromdouble 1.0, |
| 298 | pyfloat_fromdouble 0.5, |
| 299 | pyfloat_fromdouble 0.2) ;; |
| 300 | |
| 301 | let rgbtoyiq = pydict_getitemstring (dict,"rgb_to_yiq") |
| 302 | let triplet = pyeval_callobject (rgbtoyiq,triplet) |
| 303 | |
| 304 | let _ = print_endline ((string_of_float |
| 305 | (pyfloat_asdouble (pytuple_getitem (triplet,0)))) ^ |
| 306 | " " ^ |
| 307 | (string_of_float |
| 308 | (pyfloat_asdouble (pytuple_getitem (triplet,1)))) ^ |
| 309 | " " ^ |
| 310 | (string_of_float |
| 311 | (pyfloat_asdouble (pytuple_getitem (triplet,2))))) ;; |
| 312 | |
| 313 | let x = pywrap_closure |
| 314 | (fun x -> print_string (pystring_asstring (pytuple_getitem (x,0))) ; |
| 315 | pynone ()) |
| 316 | |
| 317 | let _ = pyeval_callobject |
| 318 | (x,pytuple_fromsingle (pystring_fromstring "hi there")) |
| 319 | </pre> |
| 320 | </body> |
| 321 | </html> |