d0a5bbd7e3f18d551b1c64b89d138ae4bc81ada7
[ira/wip.git] / source / pidl / lib / Parse / Pidl / Samba4 / Python.pm
1 ###################################################
2 # Python function wrapper generator
3 # Copyright jelmer@samba.org 2007-2008
4 # released under the GNU GPL
5
6 package Parse::Pidl::Samba4::Python;
7
8 use Exporter;
9 @ISA = qw(Exporter);
10
11 use strict;
12 use Parse::Pidl::Typelist qw(hasType getType mapTypeName expandAlias);
13 use Parse::Pidl::Util qw(has_property ParseExpr);
14 use Parse::Pidl::CUtil qw(get_value_of get_pointer_to);
15
16 use vars qw($VERSION);
17 $VERSION = '0.01';
18
19 sub new($) {
20         my ($class) = @_;
21         my $self = { res => "", res_hdr => "", tabs => "", constants => {},
22                      module_methods => []};
23         bless($self, $class);
24 }
25
26 sub pidl_hdr ($$)
27 {
28         my $self = shift;
29         $self->{res_hdr} .= shift;
30 }
31
32 sub pidl($$)
33 {
34         my ($self, $d) = @_;
35         if ($d) {
36                 $self->{res} .= $self->{tabs};
37                 $self->{res} .= $d;
38         }
39         $self->{res} .= "\n";
40 }
41
42 sub indent($)
43 {
44         my ($self) = @_;
45         $self->{tabs} .= "\t";
46 }
47
48 sub deindent($)
49 {
50         my ($self) = @_;
51         $self->{tabs} = substr($self->{tabs}, 0, -1);
52 }
53
54 sub Import
55 {
56         my $self = shift;
57         my @imports = @_;
58         foreach (@imports) {
59                 s/\.idl\"$//;
60                 s/^\"//;
61                 $self->pidl_hdr("#include \"librpc/gen_ndr/py_$_\.h\"\n");
62         }
63 }
64
65 sub Const($$)
66 {
67     my ($self, $const) = @_;
68         $self->register_constant($const->{NAME}, $const->{DTYPE}, $const->{VALUE});
69 }
70
71 sub register_constant($$$$)
72 {
73         my ($self, $name, $type, $value) = @_;
74
75         $self->{constants}->{$name} = [$type, $value];
76 }
77
78 sub EnumAndBitmapConsts($$$)
79 {
80         my ($self, $name, $d) = @_;
81
82         return unless (defined($d->{ELEMENTS}));
83
84         foreach my $e (@{$d->{ELEMENTS}}) {
85                 $e =~ /^([A-Za-z0-9_]+)=(.*)$/;
86                 my $cname = $1;
87                 
88                 $self->register_constant($cname, $d, $cname);
89         }
90 }
91
92 sub FromUnionToPythonFunction($$)
93 {
94         my ($self, $type) = @_;
95
96         #FIXME
97
98         $self->pidl("return NULL;");
99 }
100
101 sub FromStructToPythonFunction($$)
102 {
103         my ($self, $type) = @_;
104
105         #FIXME
106         $self->pidl("return NULL;");
107 }
108
109 sub FromPythonToUnionFunction($$)
110 {
111         my ($self, $type) = @_;
112
113         #FIXME
114         $self->pidl("return NULL;");
115 }
116
117 sub FromPythonToStructFunction($$)
118 {
119         my ($self, $type) = @_;
120
121         #FIXME
122         $self->pidl("return NULL;");
123 }
124
125 sub PythonStruct($$$$)
126 {
127         my ($self, $name, $cname, $d) = @_;
128
129         $self->pidl("staticforward PyTypeObject $name\_ObjectType;");
130         $self->pidl("typedef struct {");
131         $self->indent;
132         $self->pidl("PyObject_HEAD");
133         $self->pidl("$cname *object;");
134         $self->deindent;
135         $self->pidl("} $name\_Object;");
136
137         $self->pidl("");
138
139         $self->pidl("static PyObject *py_$name\_getattr(PyTypeObject *obj, char *name)");
140         $self->pidl("{");
141         $self->indent;
142         $self->pidl("$name\_Object *py_object = ($name\_Object *)obj;");
143         $self->pidl("$cname *object = talloc_get_type(py_object->object, $cname);");
144         foreach my $e (@{$d->{ELEMENTS}}) {
145                 $self->pidl("if (!strcmp(name, \"$e->{NAME}\")) {");
146                 my $varname = "object->$e->{NAME}";
147                 $self->indent;
148                 $self->pidl("return ".$self->ConvertObjectToPython($e->{TYPE}, $varname) . ";");
149                 $self->deindent;
150                 $self->pidl("}");
151         }
152         $self->pidl("PyErr_SetString(PyExc_AttributeError, \"no such attribute\");");
153         $self->pidl("return NULL;");
154         $self->deindent;
155         $self->pidl("}");
156         $self->pidl("");
157
158         $self->pidl("static void py_$name\_dealloc(PyObject* self)");
159         $self->pidl("{");
160         $self->indent;
161         $self->pidl("$name\_Object *obj = ($name\_Object *)self;");
162         $self->pidl("talloc_free(obj->object);");
163         $self->pidl("PyObject_Del(self);");
164         $self->deindent;
165         $self->pidl("}");
166         $self->pidl("");
167
168         $self->pidl("static PyObject *py_$name\_setattr(PyTypeObject *obj, char *name, PyObject *value)");
169         $self->pidl("{");
170         $self->indent;
171         $self->pidl("$name\_Object *py_object = ($name\_Object *)obj;");
172         $self->pidl("$cname *object = talloc_get_type(py_object->object, $cname);");
173         foreach my $e (@{$d->{ELEMENTS}}) {
174                 $self->pidl("if (!strcmp(name, \"$e->{NAME}\")) {");
175                 my $varname = "object->$e->{NAME}";
176                 $self->indent;
177                 $self->pidl("/* FIXME: talloc_free($varname) if necessary */");
178                 $self->pidl("$varname = " . $self->ConvertObjectFromPython($e->{TYPE}, "value") . ";");
179                 $self->deindent;
180                 $self->pidl("}");
181         }
182         $self->pidl("PyErr_SetString(PyExc_AttributeError, \"no such attribute\");");
183         $self->pidl("return NULL;");
184         $self->deindent;
185         $self->pidl("}");
186         $self->pidl("");
187
188         $self->pidl("static PyTypeObject $name\_ObjectType = {");
189         $self->indent;
190         $self->pidl("PyObject_HEAD_INIT(NULL) 0,");
191         $self->pidl(".tp_name = \"$name\",");
192         $self->pidl(".tp_basicsize = sizeof($name\_Object),");
193         $self->pidl(".tp_dealloc = (destructor)py_$name\_dealloc,");
194         $self->pidl(".tp_getattr = (getattrfunc)py_$name\_getattr,");
195         $self->pidl(".tp_setattr = (setattrfunc)py_$name\_setattr,");
196         $self->deindent;
197         $self->pidl("};");
198
199         $self->pidl("");
200
201         my $py_fnname = "py_$name";
202         $self->pidl("static PyObject *$py_fnname(PyObject *self, PyObject *args)");
203         $self->pidl("{");
204         $self->indent;
205         $self->pidl("$name\_Object *ret;");
206         $self->pidl("ret = PyObject_New($name\_Object, &$name\_ObjectType);");
207         $self->pidl("return (PyObject *) ret;");
208         $self->deindent;
209         $self->pidl("}");
210         $self->pidl("");
211
212         return $py_fnname;
213 }
214
215 sub PythonFunction($$$)
216 {
217         my ($self, $fn, $iface) = @_;
218
219         $self->pidl("static PyObject *py_$fn->{NAME}(PyObject *self, PyObject *args)");
220         $self->pidl("{");
221         $self->indent;
222         $self->pidl("$iface\_InterfaceObject *iface = ($iface\_InterfaceObject *)self;");
223         $self->pidl("NTSTATUS status;");
224         $self->pidl("TALLOC_CTX *mem_ctx = talloc_new(NULL);");
225         $self->pidl("struct dcerpc_$fn->{NAME} r;");
226         $self->pidl("PyObject *result;");
227         my $result_size = 0;
228
229         foreach my $e (@{$fn->{ELEMENTS}}) {
230                 if (grep(/in/,@{$e->{DIRECTION}})) {
231                         $self->pidl("PyObject *py_$e->{NAME};");
232                 }
233                 if (grep(/out/,@{$e->{DIRECTION}})) {
234                         $result_size++;
235                 }
236         }
237         if ($fn->{RETURN_TYPE}) {
238                 $result_size++;
239         }
240         $self->pidl("");
241         $self->pidl("ZERO_STRUCT(r.out);");
242
243         foreach my $e (@{$fn->{ELEMENTS}}) {
244                 if (grep(/in/,@{$e->{DIRECTION}})) {
245                         $self->pidl("r.in.$e->{NAME} = " . $self->ConvertObjectFromPython($e->{TYPE}, "py_$e->{NAME}") . ";");
246                 }
247         }
248         $self->pidl("status = dcerpc_$fn->{NAME}(iface->pipe, mem_ctx, &r);");
249         $self->handle_ntstatus("status", "NULL", "mem_ctx");
250
251         $self->pidl("result = PyTuple_New($result_size);");
252
253         my $i = 0;
254
255         foreach my $e (@{$fn->{ELEMENTS}}) {
256                 if (grep(/out/,@{$e->{DIRECTION}})) {
257                         $self->pidl("PyTuple_SetItem(result, $i, " . $self->ConvertObjectToPython($e->{TYPE}, "r.out.$e->{NAME}") . ");");
258
259                         $i++;
260                 }
261         }
262
263         if (defined($fn->{RETURN_TYPE})) {
264                 $self->pidl("PyTuple_SetItem(result, $i, " . $self->ConvertObjectToPython($fn->{RETURN_TYPE}, "r.out.result") . ");");
265         }
266
267         $self->pidl("talloc_free(mem_ctx);");
268         $self->pidl("return result;");
269         $self->deindent;
270         $self->pidl("}");
271         $self->pidl("");
272 }
273
274 sub handle_ntstatus($$$$)
275 {
276         my ($self, $var, $retval, $mem_ctx) = @_;
277
278         $self->pidl("if (NT_STATUS_IS_ERR($var)) {");
279         $self->indent;
280         $self->pidl("PyErr_SetString(PyExc_RuntimeError, nt_errstr($var));");
281         $self->pidl("talloc_free($mem_ctx);") if ($mem_ctx);
282         $self->pidl("return $retval;");
283         $self->deindent;
284         $self->pidl("}");
285         $self->pidl("");
286 }
287
288 sub PythonType($$$)
289 {
290         my ($self, $d, $interface, $basename) = @_;
291
292         my $actual_ctype = $d;
293         if ($actual_ctype->{TYPE} eq "TYPEDEF") {
294                 $actual_ctype = $actual_ctype->{DATA};
295         }
296
297         if ($actual_ctype->{TYPE} eq "STRUCT") {
298                 my $py_fnname;
299                 if ($d->{TYPE} eq "STRUCT") {
300                         $py_fnname = $self->PythonStruct($d->{NAME}, mapTypeName($d), $d);
301                 } else {
302                         $py_fnname = $self->PythonStruct($d->{NAME}, mapTypeName($d), $d->{DATA});
303                 }
304
305                 my $fn_name = $d->{NAME};
306
307                 $fn_name =~ s/^$interface->{NAME}_//;
308                 $fn_name =~ s/^$basename\_//;
309
310                 $self->register_module_method($fn_name, $py_fnname, "METH_VARARGS|METH_KEYWORDS", "NULL");
311         }
312
313         if ($d->{TYPE} eq "ENUM" or $d->{TYPE} eq "BITMAP") {
314                 $self->EnumAndBitmapConsts($d->{NAME}, $d);
315         }
316
317         if ($d->{TYPE} eq "TYPEDEF" and ($d->{DATA}->{TYPE} eq "ENUM" or $d->{DATA}->{TYPE} eq "BITMAP")) {
318                 $self->EnumAndBitmapConsts($d->{NAME}, $d->{DATA});
319         }
320
321         if ($actual_ctype->{TYPE} eq "UNION" or $actual_ctype->{TYPE} eq "STRUCT") {
322                 $self->pidl("PyObject *py_import_$d->{NAME}(" .mapTypeName($d) . " *in)");
323                 $self->pidl("{");
324                 $self->indent;
325                 $self->FromStructToPythonFunction($d) if ($actual_ctype->{TYPE} eq "STRUCT");
326                 $self->FromUnionToPythonFunction($d) if ($actual_ctype->{TYPE} eq "UNION");
327                 $self->deindent;
328                 $self->pidl("}");
329                 $self->pidl("");
330
331                 $self->pidl(mapTypeName($d) . " *py_export_$d->{NAME}(TALLOC_CTX *mem_ctx, PyObject *in)");
332                 $self->pidl("{");
333                 $self->indent;
334                 $self->FromPythonToStructFunction($d) if ($actual_ctype->{TYPE} eq "STRUCT");
335                 $self->FromPythonToUnionFunction($d) if ($actual_ctype->{TYPE} eq "UNION");
336                 $self->deindent;
337                 $self->pidl("}");
338                 $self->pidl("");
339         }
340 }
341
342 sub Interface($$$)
343 {
344         my($self,$interface,$basename) = @_;
345
346         $self->pidl_hdr("#ifndef _HEADER_PYTHON_$interface->{NAME}\n");
347         $self->pidl_hdr("#define _HEADER_PYTHON_$interface->{NAME}\n\n");
348
349         $self->pidl_hdr("\n");
350
351         $self->Const($_) foreach (@{$interface->{CONSTS}});
352
353         foreach my $d (@{$interface->{TYPES}}) {
354                 next if has_property($d, "nopython");
355
356                 $self->PythonType($d, $interface, $basename);
357         }
358
359         $self->pidl("staticforward PyTypeObject $interface->{NAME}_InterfaceType;");
360         $self->pidl("typedef struct {");
361         $self->indent;
362         $self->pidl("PyObject_HEAD");
363         $self->pidl("struct dcerpc_pipe *pipe;");
364         $self->deindent;
365         $self->pidl("} $interface->{NAME}_InterfaceObject;");
366
367         $self->pidl("");
368
369         foreach my $d (@{$interface->{FUNCTIONS}}) {
370                 next if not defined($d->{OPNUM});
371                 next if has_property($d, "nopython");
372
373                 $self->PythonFunction($d, $interface->{NAME});
374         }
375
376         $self->pidl("static PyMethodDef interface_$interface->{NAME}\_methods[] = {");
377         $self->indent;
378         foreach my $d (@{$interface->{FUNCTIONS}}) {
379                 next if not defined($d->{OPNUM});
380                 next if has_property($d, "nopython");
381
382                 my $fn_name = $d->{NAME};
383
384                 $fn_name =~ s/^$interface->{NAME}_//;
385
386                 $self->pidl("{ \"$fn_name\", (PyCFunction)py_$d->{NAME}, METH_VARARGS|METH_KEYWORDS, NULL },");
387         }
388         $self->pidl("{ NULL, NULL, 0, NULL }");
389         $self->deindent;
390         $self->pidl("};");
391         $self->pidl("");
392
393         $self->pidl("static void interface_$interface->{NAME}_dealloc(PyObject* self)");
394         $self->pidl("{");
395         $self->indent;
396         $self->pidl("$interface->{NAME}_InterfaceObject *interface = ($interface->{NAME}_InterfaceObject *)self;");
397         $self->pidl("talloc_free(interface->pipe);");
398         $self->pidl("PyObject_Del(self);");
399         $self->deindent;
400         $self->pidl("}");
401         $self->pidl("");
402
403         $self->pidl("static PyObject *interface_$interface->{NAME}_getattr(PyTypeObject *obj, char *name)");
404         $self->pidl("{");
405         $self->indent;
406         $self->pidl("return Py_FindMethod(interface_$interface->{NAME}\_methods, (PyObject *)obj, name);");
407         $self->deindent;
408         $self->pidl("}");
409
410         $self->pidl("");
411
412         $self->pidl("static PyTypeObject $interface->{NAME}_InterfaceType = {");
413         $self->indent;
414         $self->pidl("PyObject_HEAD_INIT(NULL) 0,");
415         $self->pidl(".tp_name = \"$interface->{NAME}\",");
416         $self->pidl(".tp_basicsize = sizeof($interface->{NAME}_InterfaceObject),");
417         $self->pidl(".tp_dealloc = interface_$interface->{NAME}_dealloc,");
418         $self->pidl(".tp_getattr = interface_$interface->{NAME}_getattr,");
419         $self->deindent;
420         $self->pidl("};");
421
422         $self->pidl("");
423
424         $self->register_module_method($interface->{NAME}, "interface_$interface->{NAME}", "METH_VARARGS|METH_KEYWORDS", "NULL");
425         $self->pidl("static PyObject *interface_$interface->{NAME}(PyObject *self, PyObject *args)");
426         $self->pidl("{");
427         $self->indent;
428         $self->pidl("$interface->{NAME}_InterfaceObject *ret;");
429         $self->pidl("const char *binding_string;");
430         $self->pidl("struct cli_credentials *credentials;");
431         $self->pidl("struct loadparm_context *lp_ctx;");
432         $self->pidl("TALLOC_CTX *mem_ctx = NULL;");
433         $self->pidl("NTSTATUS status;");
434         $self->pidl("");
435
436         # FIXME: Arguments: binding string, credentials, loadparm context
437         $self->pidl("ret = PyObject_New($interface->{NAME}_InterfaceObject, &$interface->{NAME}_InterfaceType);");
438         $self->pidl("");
439
440         $self->pidl("status = dcerpc_pipe_connect(NULL, &ret->pipe, binding_string, ");
441         $self->pidl("             &ndr_table_$interface->{NAME}, credentials, NULL, lp_ctx);");
442         $self->handle_ntstatus("status", "NULL", "mem_ctx");
443
444         $self->pidl("return (PyObject *)ret;");
445         $self->deindent;
446         $self->pidl("}");
447         
448         $self->pidl("");
449
450         $self->pidl_hdr("\n");
451         $self->pidl_hdr("#endif /* _HEADER_NDR_$interface->{NAME} */\n");
452 }
453
454 sub register_module_method($$$$$)
455 {
456         my ($self, $fn_name, $pyfn_name, $flags, $doc) = @_;
457
458         push (@{$self->{module_methods}}, [$fn_name, $pyfn_name, $flags, $doc])
459 }
460
461 sub ConvertObjectFromPython($$$)
462 {
463         my ($self, $ctype, $cvar) = @_;
464
465         die("undef type for $cvar") unless(defined($ctype));
466
467         if (ref($ctype) ne "HASH") {
468                 $ctype = getType($ctype);
469         }
470
471         if (ref($ctype) ne "HASH") {
472                 return "FIXME($cvar)";
473         }
474
475         my $actual_ctype = $ctype;
476         if ($ctype->{TYPE} eq "TYPEDEF") {
477                 $actual_ctype = $ctype->{DATA};
478         }
479
480         if ($actual_ctype->{TYPE} eq "ENUM" or $actual_ctype->{TYPE} eq "BITMAP" or 
481                 $actual_ctype->{TYPE} eq "SCALAR" and (
482                 expandAlias($actual_ctype->{NAME}) =~ /^(uint[0-9]+|hyper|NTTIME|time_t|NTTIME_hyper|NTTIME_1sec|dlong|udlong)$/)) {
483                 return "PyInt_AsLong($cvar)";
484         }
485
486         return "FIXME($cvar)";
487 }
488
489 sub ConvertObjectToPython($$$)
490 {
491         my ($self, $ctype, $cvar) = @_;
492
493         if ($cvar =~ /^[0-9]+$/ or $cvar =~ /^0x[0-9a-fA-F]+$/) {
494                 return "PyInt_FromLong($cvar)";
495         }
496
497         die("undef type for $cvar") unless(defined($ctype));
498
499         if ($cvar =~ /^".*"$/) {
500                 return "PyString_FromString($cvar)";
501         }
502
503         if (ref($ctype) ne "HASH") {
504                 if (not hasType($ctype)) {
505                         if (ref($ctype) eq "HASH") {
506                                 return "py_import_$ctype->{TYPE}_$ctype->{NAME}($cvar)";
507                         } else {
508                                 return "py_import_$ctype($cvar)"; # best bet
509                         }
510                 }
511
512                 $ctype = getType($ctype);
513         }
514
515         my $actual_ctype = $ctype;
516         if ($ctype->{TYPE} eq "TYPEDEF") {
517                 $actual_ctype = $ctype->{DATA};
518         }
519
520         if ($actual_ctype->{TYPE} eq "ENUM" or $actual_ctype->{TYPE} eq "BITMAP" or 
521                 ($actual_ctype->{TYPE} eq "SCALAR" and 
522                 expandAlias($actual_ctype->{NAME}) =~ /^(int|long|char|u?int[0-9]+|hyper|dlong|udlong|udlongr|time_t|NTTIME_hyper|NTTIME|NTTIME_1sec)$/)) {
523                 return "PyInt_FromLong($cvar)";
524         }
525
526         if ($ctype->{TYPE} eq "TYPEDEF" and (
527                         $actual_ctype->{TYPE} eq "STRUCT" or 
528                         $actual_ctype->{TYPE} eq "UNION")) {
529                 return "py_import_$ctype->{NAME}($cvar)";
530         }
531
532         if ($actual_ctype->{TYPE} eq "SCALAR" and 
533                 expandAlias($actual_ctype->{NAME}) eq "DATA_BLOB") {
534                 return "PyString_FromStringAndSize($cvar->data, $cvar->length)";
535         }
536
537         if ($ctype->{TYPE} eq "STRUCT" or $ctype->{TYPE} eq "UNION") {
538                 return "py_import_$ctype->{TYPE}_$ctype->{NAME}($cvar)";
539         }
540
541         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "NTSTATUS") {
542                 return "PyInt_FromLong($cvar->v)";
543         }
544
545         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "WERROR") {
546                 return "PyInt_FromLong($cvar->v)";
547         }
548
549         if ($actual_ctype->{TYPE} eq "SCALAR" and 
550                 ($actual_ctype->{NAME} eq "string" or $actual_ctype->{NAME} eq "nbt_string" or $actual_ctype->{NAME} eq "nbt_name" or $actual_ctype->{NAME} eq "wrepl_nbt_name")) {
551                 return "PyString_FromString($cvar)";
552         }
553
554         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "string_array") {
555                 return "FIXME($cvar)";
556         }
557
558         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "ipv4address") {
559                 return "FIXME($cvar)";
560                 }
561
562         if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "pointer") {
563                 return "PyCObject_FromVoidPtr($cvar, talloc_free)";
564         }
565
566
567         die("unknown type ".mapTypeName($ctype) . ": $cvar");
568 }
569
570 sub Parse($$$$)
571 {
572     my($self,$basename,$ndr,$hdr) = @_;
573     
574     my $py_hdr = $hdr;
575     $py_hdr =~ s/ndr_([^\/]+)$/py_$1/g;
576
577     $self->pidl_hdr("/* header auto-generated by pidl */\n\n");
578         
579     $self->pidl("
580 /* Python wrapper functions auto-generated by pidl */
581 #include \"includes.h\"
582 #include <Python.h>
583 #include \"librpc/rpc/dcerpc.h\"
584 #include \"$hdr\"
585 #include \"$py_hdr\"
586
587 ");
588
589         foreach my $x (@$ndr) {
590             ($x->{TYPE} eq "INTERFACE") && $self->Interface($x, $basename);
591                 ($x->{TYPE} eq "IMPORT") && $self->Import(@{$x->{PATHS}});
592         }
593         
594         $self->pidl("static PyMethodDef $basename\_methods[] = {");
595         $self->indent;
596         foreach (@{$self->{module_methods}}) {
597                 my ($fn_name, $pyfn_name, $flags, $doc) = @$_;
598                 $self->pidl("{ \"$fn_name\", (PyCFunction)$pyfn_name, $flags, $doc },");
599         }
600         
601         $self->pidl("{ NULL, NULL, 0, NULL }");
602         $self->deindent;
603         $self->pidl("};");
604
605         $self->pidl("");
606
607         $self->pidl("void init$basename(void)");
608         $self->pidl("{");
609         $self->indent;
610         $self->pidl("PyObject *m;");
611         $self->pidl("m = Py_InitModule(\"$basename\", $basename\_methods);");
612         foreach (keys %{$self->{constants}}) {
613                 # FIXME: Handle non-string constants
614                 $self->pidl("PyModule_AddObject(m, \"$_\", " .  $self->ConvertObjectToPython($self->{constants}->{$_}->[0], $self->{constants}->{$_}->[1]) . ");");
615         }
616         $self->deindent;
617         $self->pidl("}");
618     return ($self->{res_hdr}, $self->{res});
619 }
620
621 1;