1 ###################################################
2 # Python function wrapper generator
3 # Copyright jelmer@samba.org 2007-2008
4 # released under the GNU GPL
6 package Parse::Pidl::Samba4::Python;
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);
16 use vars qw($VERSION);
21 my $self = { res => "", res_hdr => "", tabs => "", constants => {},
22 module_methods => []};
29 $self->{res_hdr} .= shift;
36 $self->{res} .= $self->{tabs};
45 $self->{tabs} .= "\t";
51 $self->{tabs} = substr($self->{tabs}, 0, -1);
61 $self->pidl_hdr("#include \"librpc/gen_ndr/py_$_\.h\"\n");
67 my ($self, $const) = @_;
68 $self->register_constant($const->{NAME}, $const->{DTYPE}, $const->{VALUE});
71 sub register_constant($$$$)
73 my ($self, $name, $type, $value) = @_;
75 $self->{constants}->{$name} = [$type, $value];
78 sub EnumAndBitmapConsts($$$)
80 my ($self, $name, $d) = @_;
82 return unless (defined($d->{ELEMENTS}));
84 foreach my $e (@{$d->{ELEMENTS}}) {
85 $e =~ /^([A-Za-z0-9_]+)=(.*)$/;
88 $self->register_constant($cname, $d, $cname);
92 sub FromUnionToPythonFunction($$$)
94 my ($self, $type, $name) = @_;
98 $self->pidl("return NULL;");
101 sub FromStructToPythonFunction($$$)
103 my ($self, $type, $name) = @_;
105 $self->pidl("$type->{NAME}\_Object *ret;");
106 $self->pidl("ret = PyObject_New($type->{NAME}\_Object, &$type->{NAME}\_ObjectType);");
107 $self->pidl("ret->object = talloc_reference(NULL, $name);");
108 $self->pidl("return (PyObject *) ret;");
111 sub FromPythonToUnionFunction($$$$)
113 my ($self, $type, $mem_ctx, $name) = @_;
116 $self->pidl("return NULL;");
119 sub FromPythonToStructFunction($$$$)
121 my ($self, $type, $mem_ctx, $name) = @_;
123 $self->pidl("$type->{NAME}\_Object *py_object = ($type->{NAME}_Object *)$name;");
124 $self->pidl("return talloc_reference($mem_ctx, py_object->object);");
127 sub PythonStruct($$$$)
129 my ($self, $name, $cname, $d) = @_;
131 $self->pidl("staticforward PyTypeObject $name\_ObjectType;");
132 $self->pidl("typedef struct {");
134 $self->pidl("PyObject_HEAD");
135 $self->pidl("$cname *object;");
137 $self->pidl("} $name\_Object;");
141 $self->pidl("static PyObject *py_$name\_getattr(PyTypeObject *obj, char *name)");
144 $self->pidl("$name\_Object *py_object = ($name\_Object *)obj;");
145 $self->pidl("$cname *object = talloc_get_type(py_object->object, $cname);");
146 foreach my $e (@{$d->{ELEMENTS}}) {
147 $self->pidl("if (!strcmp(name, \"$e->{NAME}\")) {");
148 my $varname = "object->$e->{NAME}";
150 $self->pidl("return ".$self->ConvertObjectToPython($e->{TYPE}, $varname) . ";");
154 $self->pidl("PyErr_SetString(PyExc_AttributeError, \"no such attribute\");");
155 $self->pidl("return NULL;");
160 $self->pidl("static void py_$name\_dealloc(PyObject* self)");
163 $self->pidl("$name\_Object *obj = ($name\_Object *)self;");
164 $self->pidl("talloc_free(obj->object);");
165 $self->pidl("PyObject_Del(self);");
170 $self->pidl("static PyObject *py_$name\_setattr(PyTypeObject *obj, char *name, PyObject *value)");
173 $self->pidl("$name\_Object *py_object = ($name\_Object *)obj;");
174 $self->pidl("$cname *object = talloc_get_type(py_object->object, $cname);");
175 foreach my $e (@{$d->{ELEMENTS}}) {
176 $self->pidl("if (!strcmp(name, \"$e->{NAME}\")) {");
177 my $varname = "object->$e->{NAME}";
179 $self->pidl("/* FIXME: talloc_free($varname) if necessary */");
180 $self->pidl("$varname = " . $self->ConvertObjectFromPython($e->{TYPE}, "value") . ";");
184 $self->pidl("PyErr_SetString(PyExc_AttributeError, \"no such attribute\");");
185 $self->pidl("return NULL;");
190 $self->pidl("static PyTypeObject $name\_ObjectType = {");
192 $self->pidl("PyObject_HEAD_INIT(NULL) 0,");
193 $self->pidl(".tp_name = \"$name\",");
194 $self->pidl(".tp_basicsize = sizeof($name\_Object),");
195 $self->pidl(".tp_dealloc = (destructor)py_$name\_dealloc,");
196 $self->pidl(".tp_getattr = (getattrfunc)py_$name\_getattr,");
197 $self->pidl(".tp_setattr = (setattrfunc)py_$name\_setattr,");
203 my $py_fnname = "py_$name";
204 $self->pidl("static PyObject *$py_fnname(PyObject *self, PyObject *args)");
207 $self->pidl("$name\_Object *ret;");
208 $self->pidl("ret = PyObject_New($name\_Object, &$name\_ObjectType);");
209 $self->pidl("return (PyObject *) ret;");
217 sub PythonFunction($$$)
219 my ($self, $fn, $iface) = @_;
221 $self->pidl("static PyObject *py_$fn->{NAME}(PyObject *self, PyObject *args)");
224 $self->pidl("$iface\_InterfaceObject *iface = ($iface\_InterfaceObject *)self;");
225 $self->pidl("NTSTATUS status;");
226 $self->pidl("TALLOC_CTX *mem_ctx = talloc_new(NULL);");
227 $self->pidl("struct $fn->{NAME} r;");
228 $self->pidl("PyObject *result;");
231 foreach my $e (@{$fn->{ELEMENTS}}) {
232 if (grep(/in/,@{$e->{DIRECTION}})) {
233 $self->pidl("PyObject *py_$e->{NAME};");
235 if (grep(/out/,@{$e->{DIRECTION}})) {
239 if ($result_size > 0) {
241 $self->pidl("ZERO_STRUCT(r.out);");
243 if ($fn->{RETURN_TYPE}) {
247 foreach my $e (@{$fn->{ELEMENTS}}) {
248 if (grep(/in/,@{$e->{DIRECTION}})) {
249 $self->pidl("r.in.$e->{NAME} = " . $self->ConvertObjectFromPython($e->{TYPE}, "py_$e->{NAME}") . ";");
252 $self->pidl("status = dcerpc_$fn->{NAME}(iface->pipe, mem_ctx, &r);");
253 $self->handle_ntstatus("status", "NULL", "mem_ctx");
255 $self->pidl("result = PyTuple_New($result_size);");
259 foreach my $e (@{$fn->{ELEMENTS}}) {
260 if (grep(/out/,@{$e->{DIRECTION}})) {
261 $self->pidl("PyTuple_SetItem(result, $i, " . $self->ConvertObjectToPython($e->{TYPE}, "r.out.$e->{NAME}") . ");");
267 if (defined($fn->{RETURN_TYPE})) {
268 $self->pidl("PyTuple_SetItem(result, $i, " . $self->ConvertObjectToPython($fn->{RETURN_TYPE}, "r.out.result") . ");");
271 $self->pidl("talloc_free(mem_ctx);");
272 $self->pidl("return result;");
278 sub handle_ntstatus($$$$)
280 my ($self, $var, $retval, $mem_ctx) = @_;
282 $self->pidl("if (NT_STATUS_IS_ERR($var)) {");
284 $self->pidl("PyErr_SetString(PyExc_RuntimeError, nt_errstr($var));");
285 $self->pidl("talloc_free($mem_ctx);") if ($mem_ctx);
286 $self->pidl("return $retval;");
294 my ($self, $d, $interface, $basename) = @_;
296 my $actual_ctype = $d;
297 if ($actual_ctype->{TYPE} eq "TYPEDEF") {
298 $actual_ctype = $actual_ctype->{DATA};
301 if ($actual_ctype->{TYPE} eq "STRUCT") {
303 if ($d->{TYPE} eq "STRUCT") {
304 $py_fnname = $self->PythonStruct($d->{NAME}, mapTypeName($d), $d);
306 $py_fnname = $self->PythonStruct($d->{NAME}, mapTypeName($d), $d->{DATA});
309 my $fn_name = $d->{NAME};
311 $fn_name =~ s/^$interface->{NAME}_//;
312 $fn_name =~ s/^$basename\_//;
314 $self->register_module_method($fn_name, $py_fnname, "METH_VARARGS|METH_KEYWORDS", "NULL");
317 if ($d->{TYPE} eq "ENUM" or $d->{TYPE} eq "BITMAP") {
318 $self->EnumAndBitmapConsts($d->{NAME}, $d);
321 if ($d->{TYPE} eq "TYPEDEF" and ($d->{DATA}->{TYPE} eq "ENUM" or $d->{DATA}->{TYPE} eq "BITMAP")) {
322 $self->EnumAndBitmapConsts($d->{NAME}, $d->{DATA});
325 if ($actual_ctype->{TYPE} eq "UNION" or $actual_ctype->{TYPE} eq "STRUCT") {
326 $self->pidl("PyObject *py_import_$d->{NAME}(" .mapTypeName($d) . " *in)");
329 $self->FromStructToPythonFunction($d, "in") if ($actual_ctype->{TYPE} eq "STRUCT");
330 $self->FromUnionToPythonFunction($d, "in") if ($actual_ctype->{TYPE} eq "UNION");
335 $self->pidl(mapTypeName($d) . " *py_export_$d->{NAME}(TALLOC_CTX *mem_ctx, PyObject *in)");
338 $self->FromPythonToStructFunction($d, "mem_ctx", "in") if ($actual_ctype->{TYPE} eq "STRUCT");
339 $self->FromPythonToUnionFunction($d, "mem_ctx", "in") if ($actual_ctype->{TYPE} eq "UNION");
348 my($self,$interface,$basename) = @_;
350 $self->pidl_hdr("#ifndef _HEADER_PYTHON_$interface->{NAME}\n");
351 $self->pidl_hdr("#define _HEADER_PYTHON_$interface->{NAME}\n\n");
353 $self->pidl_hdr("\n");
355 $self->Const($_) foreach (@{$interface->{CONSTS}});
357 foreach my $d (@{$interface->{TYPES}}) {
358 next if has_property($d, "nopython");
360 $self->PythonType($d, $interface, $basename);
363 $self->pidl("staticforward PyTypeObject $interface->{NAME}_InterfaceType;");
364 $self->pidl("typedef struct {");
366 $self->pidl("PyObject_HEAD");
367 $self->pidl("struct dcerpc_pipe *pipe;");
369 $self->pidl("} $interface->{NAME}_InterfaceObject;");
373 foreach my $d (@{$interface->{FUNCTIONS}}) {
374 next if not defined($d->{OPNUM});
375 next if has_property($d, "nopython");
377 $self->PythonFunction($d, $interface->{NAME});
380 $self->pidl("static PyMethodDef interface_$interface->{NAME}\_methods[] = {");
382 foreach my $d (@{$interface->{FUNCTIONS}}) {
383 next if not defined($d->{OPNUM});
384 next if has_property($d, "nopython");
386 my $fn_name = $d->{NAME};
388 $fn_name =~ s/^$interface->{NAME}_//;
390 $self->pidl("{ \"$fn_name\", (PyCFunction)py_$d->{NAME}, METH_VARARGS|METH_KEYWORDS, NULL },");
392 $self->pidl("{ NULL, NULL, 0, NULL }");
397 $self->pidl("static void interface_$interface->{NAME}_dealloc(PyObject* self)");
400 $self->pidl("$interface->{NAME}_InterfaceObject *interface = ($interface->{NAME}_InterfaceObject *)self;");
401 $self->pidl("talloc_free(interface->pipe);");
402 $self->pidl("PyObject_Del(self);");
407 $self->pidl("static PyObject *interface_$interface->{NAME}_getattr(PyTypeObject *obj, char *name)");
410 $self->pidl("return Py_FindMethod(interface_$interface->{NAME}\_methods, (PyObject *)obj, name);");
416 $self->pidl("static PyTypeObject $interface->{NAME}_InterfaceType = {");
418 $self->pidl("PyObject_HEAD_INIT(NULL) 0,");
419 $self->pidl(".tp_name = \"$interface->{NAME}\",");
420 $self->pidl(".tp_basicsize = sizeof($interface->{NAME}_InterfaceObject),");
421 $self->pidl(".tp_dealloc = (destructor)interface_$interface->{NAME}_dealloc,");
422 $self->pidl(".tp_getattr = (getattrfunc)interface_$interface->{NAME}_getattr,");
428 $self->register_module_method($interface->{NAME}, "interface_$interface->{NAME}", "METH_VARARGS|METH_KEYWORDS", "NULL");
429 $self->pidl("static PyObject *interface_$interface->{NAME}(PyObject *self, PyObject *args)");
432 $self->pidl("$interface->{NAME}_InterfaceObject *ret;");
433 $self->pidl("const char *binding_string;");
434 $self->pidl("struct cli_credentials *credentials;");
435 $self->pidl("struct loadparm_context *lp_ctx;");
436 $self->pidl("TALLOC_CTX *mem_ctx = NULL;");
437 $self->pidl("NTSTATUS status;");
440 # FIXME: Arguments: binding string, credentials, loadparm context
441 $self->pidl("ret = PyObject_New($interface->{NAME}_InterfaceObject, &$interface->{NAME}_InterfaceType);");
444 $self->pidl("status = dcerpc_pipe_connect(NULL, &ret->pipe, binding_string, ");
445 $self->pidl(" &ndr_table_$interface->{NAME}, credentials, NULL, lp_ctx);");
446 $self->handle_ntstatus("status", "NULL", "mem_ctx");
448 $self->pidl("return (PyObject *)ret;");
454 $self->pidl_hdr("\n");
455 $self->pidl_hdr("#endif /* _HEADER_NDR_$interface->{NAME} */\n");
458 sub register_module_method($$$$$)
460 my ($self, $fn_name, $pyfn_name, $flags, $doc) = @_;
462 push (@{$self->{module_methods}}, [$fn_name, $pyfn_name, $flags, $doc])
465 sub ConvertObjectFromPython($$$)
467 my ($self, $ctype, $cvar) = @_;
469 die("undef type for $cvar") unless(defined($ctype));
471 if (ref($ctype) ne "HASH") {
472 $ctype = getType($ctype);
475 if (ref($ctype) ne "HASH") {
476 return "FIXME($cvar)";
479 my $actual_ctype = $ctype;
480 if ($ctype->{TYPE} eq "TYPEDEF") {
481 $actual_ctype = $ctype->{DATA};
484 if ($actual_ctype->{TYPE} eq "ENUM" or $actual_ctype->{TYPE} eq "BITMAP" or
485 $actual_ctype->{TYPE} eq "SCALAR" and (
486 expandAlias($actual_ctype->{NAME}) =~ /^(uint[0-9]+|hyper|NTTIME|time_t|NTTIME_hyper|NTTIME_1sec|dlong|udlong)$/)) {
487 return "PyInt_AsLong($cvar)";
490 return "FIXME($cvar)";
493 sub ConvertObjectToPython($$$)
495 my ($self, $ctype, $cvar) = @_;
497 if ($cvar =~ /^[0-9]+$/ or $cvar =~ /^0x[0-9a-fA-F]+$/) {
498 return "PyInt_FromLong($cvar)";
501 die("undef type for $cvar") unless(defined($ctype));
503 if ($cvar =~ /^".*"$/) {
504 return "PyString_FromString($cvar)";
507 if (ref($ctype) ne "HASH") {
508 if (not hasType($ctype)) {
509 if (ref($ctype) eq "HASH") {
510 return "py_import_$ctype->{TYPE}_$ctype->{NAME}($cvar)";
512 return "py_import_$ctype($cvar)"; # best bet
516 $ctype = getType($ctype);
519 my $actual_ctype = $ctype;
520 if ($ctype->{TYPE} eq "TYPEDEF") {
521 $actual_ctype = $ctype->{DATA};
524 if ($actual_ctype->{TYPE} eq "ENUM" or $actual_ctype->{TYPE} eq "BITMAP" or
525 ($actual_ctype->{TYPE} eq "SCALAR" and
526 expandAlias($actual_ctype->{NAME}) =~ /^(int|long|char|u?int[0-9]+|hyper|dlong|udlong|udlongr|time_t|NTTIME_hyper|NTTIME|NTTIME_1sec)$/)) {
527 return "PyInt_FromLong($cvar)";
530 if ($ctype->{TYPE} eq "TYPEDEF" and (
531 $actual_ctype->{TYPE} eq "STRUCT" or
532 $actual_ctype->{TYPE} eq "UNION")) {
533 return "py_import_$ctype->{NAME}($cvar)";
536 if ($actual_ctype->{TYPE} eq "SCALAR" and
537 expandAlias($actual_ctype->{NAME}) eq "DATA_BLOB") {
538 return "PyString_FromStringAndSize($cvar->data, $cvar->length)";
541 if ($ctype->{TYPE} eq "STRUCT" or $ctype->{TYPE} eq "UNION") {
542 return "py_import_$ctype->{TYPE}_$ctype->{NAME}($cvar)";
545 if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "NTSTATUS") {
546 return "PyInt_FromLong($cvar->v)";
549 if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "WERROR") {
550 return "PyInt_FromLong($cvar->v)";
553 if ($actual_ctype->{TYPE} eq "SCALAR" and
554 ($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")) {
555 return "PyString_FromString($cvar)";
558 if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "string_array") {
559 return "FIXME($cvar)";
562 if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "ipv4address") {
563 return "FIXME($cvar)";
566 if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "pointer") {
567 return "PyCObject_FromVoidPtr($cvar, talloc_free)";
571 die("unknown type ".mapTypeName($ctype) . ": $cvar");
576 my($self,$basename,$ndr,$ndr_hdr,$hdr) = @_;
579 $py_hdr =~ s/ndr_([^\/]+)$/py_$1/g;
581 $self->pidl_hdr("/* header auto-generated by pidl */\n\n");
584 /* Python wrapper functions auto-generated by pidl */
585 #include \"includes.h\"
587 #include \"librpc/rpc/dcerpc.h\"
589 #include \"$ndr_hdr\"
594 foreach my $x (@$ndr) {
595 ($x->{TYPE} eq "INTERFACE") && $self->Interface($x, $basename);
596 ($x->{TYPE} eq "IMPORT") && $self->Import(@{$x->{PATHS}});
599 $self->pidl("static PyMethodDef $basename\_methods[] = {");
601 foreach (@{$self->{module_methods}}) {
602 my ($fn_name, $pyfn_name, $flags, $doc) = @$_;
603 $self->pidl("{ \"$fn_name\", (PyCFunction)$pyfn_name, $flags, $doc },");
606 $self->pidl("{ NULL, NULL, 0, NULL }");
612 $self->pidl("void init$basename(void)");
615 $self->pidl("PyObject *m;");
616 $self->pidl("m = Py_InitModule(\"$basename\", $basename\_methods);");
617 foreach (keys %{$self->{constants}}) {
618 # FIXME: Handle non-string constants
619 $self->pidl("PyModule_AddObject(m, \"$_\", " . $self->ConvertObjectToPython($self->{constants}->{$_}->[0], $self->{constants}->{$_}->[1]) . ");");
623 return ($self->{res_hdr}, $self->{res});