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 resolveType getType mapTypeName expandAlias);
13 use Parse::Pidl::Util qw(has_property ParseExpr);
14 use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred is_charset_array);
15 use Parse::Pidl::CUtil qw(get_value_of get_pointer_to);
16 use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv);
18 use vars qw($VERSION);
23 my $self = { res => "", res_hdr => "", tabs => "", constants => {},
24 module_methods => []};
31 $self->{res_hdr} .= shift;
38 $self->{res} .= $self->{tabs};
47 $self->{tabs} .= "\t";
53 $self->{tabs} = substr($self->{tabs}, 0, -1);
63 $self->pidl_hdr("#include \"librpc/gen_ndr/py_$_\.h\"\n");
69 my ($self, $const) = @_;
70 $self->register_constant($const->{NAME}, $const->{DTYPE}, $const->{VALUE});
73 sub register_constant($$$$)
75 my ($self, $name, $type, $value) = @_;
77 $self->{constants}->{$name} = [$type, $value];
80 sub EnumAndBitmapConsts($$$)
82 my ($self, $name, $d) = @_;
84 return unless (defined($d->{ELEMENTS}));
86 foreach my $e (@{$d->{ELEMENTS}}) {
87 $e =~ /^([A-Za-z0-9_]+)/;
90 $self->register_constant($cname, $d, $cname);
94 sub FromUnionToPythonFunction($$$$)
96 my ($self, $mem_ctx, $type, $switch, $name) = @_;
98 $self->pidl("PyObject *ret;");
101 $self->pidl("switch ($switch) {");
104 foreach my $e (@{$type->{ELEMENTS}}) {
105 $self->pidl("$e->{CASE}:");
110 $self->ConvertObjectToPython($mem_ctx, {}, $e, "$name->$e->{NAME}", "ret");
112 $self->pidl("ret = Py_None;");
115 $self->pidl("return ret;");
124 $self->pidl("PyErr_SetString(PyExc_TypeError, \"unknown union level\");");
125 $self->pidl("return NULL;");
128 sub FromPythonToUnionFunction($$$$$)
130 my ($self, $type, $typename, $switch, $mem_ctx, $name) = @_;
134 $self->pidl("$typename *ret = talloc_zero($mem_ctx, $typename);");
136 $self->pidl("switch ($switch) {");
139 foreach my $e (@{$type->{ELEMENTS}}) {
140 $self->pidl("$e->{CASE}:");
141 if ($e->{CASE} eq "default") { $has_default = 1; }
144 $self->ConvertObjectFromPython({}, $mem_ctx, $e, $name, "ret->$e->{NAME}", "talloc_free(ret); return NULL;");
146 $self->pidl("break;");
152 $self->pidl("default:");
154 $self->pidl("PyErr_SetString(PyExc_TypeError, \"invalid union level value\");");
155 $self->pidl("talloc_free(ret);");
156 $self->pidl("ret = NULL;");
163 $self->pidl("return ret;");
166 sub PythonStruct($$$$)
168 my ($self, $name, $cname, $d) = @_;
170 my $env = GenerateStructEnv($d, "object");
174 $self->pidl("static PyObject *py_$name\_getattr(PyObject *obj, char *name)");
177 if ($#{$d->{ELEMENTS}} > -1) {
178 $self->pidl("$cname *object = py_talloc_get_ptr(obj);");
179 foreach my $e (@{$d->{ELEMENTS}}) {
180 $self->pidl("if (!strcmp(name, \"$e->{NAME}\")) {");
181 my $varname = "object->$e->{NAME}";
183 $self->pidl("PyObject *py_$e->{NAME};");
184 $self->ConvertObjectToPython("py_talloc_get_mem_ctx(obj)", $env, $e, $varname, "py_$e->{NAME}");
185 $self->pidl("return py_$e->{NAME};");
190 $self->pidl("PyErr_SetString(PyExc_AttributeError, \"no such attribute\");");
191 $self->pidl("return NULL;");
196 $self->pidl("static int py_$name\_setattr(PyObject *py_obj, char *name, PyObject *value)");
199 if ($#{$d->{ELEMENTS}} > -1) {
200 $self->pidl("$cname *object = py_talloc_get_ptr(py_obj);");
201 my $mem_ctx = "py_talloc_get_mem_ctx(py_obj)";
202 foreach my $e (@{$d->{ELEMENTS}}) {
203 $self->pidl("if (!strcmp(name, \"$e->{NAME}\")) {");
204 my $varname = "object->$e->{NAME}";
206 if ($e->{ORIGINAL}->{POINTERS} > 0) {
207 $self->pidl("talloc_free($varname);");
209 $self->ConvertObjectFromPython($env, $mem_ctx, $e, "value", $varname, "return -1;");
210 $self->pidl("return 0;");
215 $self->pidl("PyErr_SetString(PyExc_AttributeError, \"no such attribute\");");
216 $self->pidl("return -1;");
221 $self->pidl_hdr("PyAPI_DATA(PyTypeObject) $name\_Type;\n");
222 $self->pidl_hdr("#define $name\_Check(op) PyObject_TypeCheck(op, &$name\_Type)\n");
223 $self->pidl_hdr("#define $name\_CheckExact(op) ((op)->ob_type == &$name\_Type)\n");
224 $self->pidl_hdr("\n");
225 $self->pidl("PyTypeObject $name\_Type = {");
227 $self->pidl("PyObject_HEAD_INIT(NULL) 0,");
228 $self->pidl(".tp_name = \"$name\",");
229 $self->pidl(".tp_basicsize = sizeof(py_talloc_Object),");
230 $self->pidl(".tp_dealloc = py_talloc_dealloc,");
231 $self->pidl(".tp_getattr = py_$name\_getattr,");
232 $self->pidl(".tp_setattr = py_$name\_setattr,");
233 $self->pidl(".tp_repr = py_talloc_default_repr,");
239 my $py_fnname = "py_$name";
240 $self->pidl("static PyObject *$py_fnname(PyObject *self, PyObject *args)");
243 $self->pidl("$cname *ret = talloc_zero(NULL, $cname);");
244 $self->pidl("return py_talloc_import(&$name\_Type, ret);");
252 sub PythonFunction($$$)
254 my ($self, $fn, $iface) = @_;
256 $self->pidl("static PyObject *py_$fn->{NAME}(PyObject *self, PyObject *args, PyObject *kwargs)");
259 $self->pidl("$iface\_InterfaceObject *iface = ($iface\_InterfaceObject *)self;");
260 $self->pidl("NTSTATUS status;");
261 $self->pidl("TALLOC_CTX *mem_ctx = talloc_new(NULL);");
262 $self->pidl("struct $fn->{NAME} *r = talloc_zero(mem_ctx, struct $fn->{NAME});");
263 $self->pidl("PyObject *result = Py_None;");
265 my $env = GenerateFunctionInEnv($fn, "r->");
268 my $args_format = "";
269 my $args_string = "";
272 foreach my $e (@{$fn->{ELEMENTS}}) {
273 $self->pidl("PyObject *py_$e->{NAME};");
274 if (grep(/out/,@{$e->{DIRECTION}})) {
277 if (grep(/in/,@{$e->{DIRECTION}})) {
279 $args_string .= ", &py_$e->{NAME}";
280 $args_names .= "\"$e->{NAME}\", ";
283 $self->pidl("const char *kwnames[] = {");
285 $self->pidl($args_names . "NULL");
290 $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"$args_format:$fn->{NAME}\", discard_const_p(char *, kwnames)$args_string)) {");
292 $self->pidl("return NULL;");
296 if ($fn->{RETURN_TYPE}) {
297 $result_size++ unless ($fn->{RETURN_TYPE} eq "WERROR" or $fn->{RETURN_TYPE} eq "NTSTATUS");
300 foreach my $e (@{$fn->{ELEMENTS}}) {
301 if (grep(/in/,@{$e->{DIRECTION}})) {
302 $self->ConvertObjectFromPython($env, "mem_ctx", $e, "py_$e->{NAME}", "r->in.$e->{NAME}", "talloc_free(mem_ctx); return NULL;");
305 $self->pidl("status = dcerpc_$fn->{NAME}(iface->pipe, mem_ctx, r);");
306 $self->handle_ntstatus("status", "NULL", "mem_ctx");
308 $env = GenerateFunctionOutEnv($fn, "r->");
311 if ($result_size > 1) {
312 $self->pidl("result = PyTuple_New($result_size);");
315 foreach my $e (@{$fn->{ELEMENTS}}) {
316 my $py_name = "py_$e->{NAME}";
317 if (grep(/out/,@{$e->{DIRECTION}})) {
318 $self->ConvertObjectToPython("r", $env, $e, "r->out.$e->{NAME}", $py_name);
319 if ($result_size > 1) {
320 $self->pidl("PyTuple_SetItem(result, $i, $py_name);");
323 $self->pidl("result = $py_name;");
328 if (defined($fn->{RETURN_TYPE}) and $fn->{RETURN_TYPE} eq "NTSTATUS") {
329 $self->handle_ntstatus("r->out.result", "NULL", "mem_ctx");
330 } elsif (defined($fn->{RETURN_TYPE}) and $fn->{RETURN_TYPE} eq "WERROR") {
331 $self->handle_werror("r->out.result", "NULL", "mem_ctx");
332 } elsif (defined($fn->{RETURN_TYPE})) {
333 my $conv = $self->ConvertObjectToPythonData("r", $fn->{RETURN_TYPE}, "r->out.result");
334 if ($result_size > 1) {
335 $self->pidl("PyTuple_SetItem(result, $i, $conv);");
337 $self->pidl("result = $conv;");
341 $self->pidl("talloc_free(mem_ctx);");
342 $self->pidl("return result;");
348 sub handle_werror($$$$)
350 my ($self, $var, $retval, $mem_ctx) = @_;
352 $self->pidl("if (!W_ERROR_IS_OK($var)) {");
354 $self->pidl("PyErr_SetString(PyExc_RuntimeError, win_errstr($var));");
355 $self->pidl("talloc_free($mem_ctx);") if ($mem_ctx);
356 $self->pidl("return $retval;");
362 sub handle_ntstatus($$$$)
364 my ($self, $var, $retval, $mem_ctx) = @_;
366 $self->pidl("if (NT_STATUS_IS_ERR($var)) {");
368 $self->pidl("PyErr_SetString(PyExc_RuntimeError, nt_errstr($var));");
369 $self->pidl("talloc_free($mem_ctx);") if ($mem_ctx);
370 $self->pidl("return $retval;");
378 my ($self, $d, $interface, $basename) = @_;
380 my $actual_ctype = $d;
381 if ($actual_ctype->{TYPE} eq "TYPEDEF") {
382 $actual_ctype = $actual_ctype->{DATA};
385 if ($actual_ctype->{TYPE} eq "STRUCT") {
387 if ($d->{TYPE} eq "STRUCT") {
388 $py_fnname = $self->PythonStruct($d->{NAME}, mapTypeName($d), $d);
390 $py_fnname = $self->PythonStruct($d->{NAME}, mapTypeName($d), $d->{DATA});
393 my $fn_name = $d->{NAME};
395 $fn_name =~ s/^$interface->{NAME}_//;
396 $fn_name =~ s/^$basename\_//;
398 $self->register_module_method($fn_name, $py_fnname, "METH_NOARGS", "NULL");
401 if ($d->{TYPE} eq "ENUM" or $d->{TYPE} eq "BITMAP") {
402 $self->EnumAndBitmapConsts($d->{NAME}, $d);
405 if ($d->{TYPE} eq "TYPEDEF" and ($d->{DATA}->{TYPE} eq "ENUM" or $d->{DATA}->{TYPE} eq "BITMAP")) {
406 $self->EnumAndBitmapConsts($d->{NAME}, $d->{DATA});
409 if ($actual_ctype->{TYPE} eq "UNION" and defined($actual_ctype->{ELEMENTS})) {
410 $self->pidl("PyObject *py_import_$d->{NAME}(TALLOC_CTX *mem_ctx, int level, " .mapTypeName($d) . " *in)");
413 $self->FromUnionToPythonFunction("mem_ctx", $actual_ctype, "level", "in") if ($actual_ctype->{TYPE} eq "UNION");
418 $self->pidl(mapTypeName($d) . " *py_export_$d->{NAME}(TALLOC_CTX *mem_ctx, int level, PyObject *in)");
421 $self->FromPythonToUnionFunction($actual_ctype, mapTypeName($d), "level", "mem_ctx", "in") if ($actual_ctype->{TYPE} eq "UNION");
430 my($self,$interface,$basename) = @_;
432 $self->pidl_hdr("#ifndef _HEADER_PYTHON_$interface->{NAME}\n");
433 $self->pidl_hdr("#define _HEADER_PYTHON_$interface->{NAME}\n\n");
435 $self->pidl_hdr("\n");
437 $self->Const($_) foreach (@{$interface->{CONSTS}});
439 foreach my $d (@{$interface->{TYPES}}) {
440 next if has_property($d, "nopython");
442 $self->PythonType($d, $interface, $basename);
445 if (defined $interface->{PROPERTIES}->{uuid}) {
446 $self->pidl_hdr("PyAPI_DATA(PyTypeObject) $interface->{NAME}_InterfaceType;\n");
447 $self->pidl("typedef struct {");
449 $self->pidl("PyObject_HEAD");
450 $self->pidl("struct dcerpc_pipe *pipe;");
452 $self->pidl("} $interface->{NAME}_InterfaceObject;");
456 foreach my $d (@{$interface->{FUNCTIONS}}) {
457 next if not defined($d->{OPNUM});
458 next if has_property($d, "nopython");
460 $self->PythonFunction($d, $interface->{NAME});
463 $self->pidl("static PyMethodDef interface_$interface->{NAME}\_methods[] = {");
465 foreach my $d (@{$interface->{FUNCTIONS}}) {
466 next if not defined($d->{OPNUM});
467 next if has_property($d, "nopython");
469 my $fn_name = $d->{NAME};
471 $fn_name =~ s/^$interface->{NAME}_//;
472 $fn_name =~ s/^$basename\_//;
474 $self->pidl("{ \"$fn_name\", (PyCFunction)py_$d->{NAME}, METH_VARARGS|METH_KEYWORDS, NULL },");
476 $self->pidl("{ NULL, NULL, 0, NULL }");
481 $self->pidl("static void interface_$interface->{NAME}_dealloc(PyObject* self)");
484 $self->pidl("$interface->{NAME}_InterfaceObject *interface = ($interface->{NAME}_InterfaceObject *)self;");
485 $self->pidl("talloc_free(interface->pipe);");
486 $self->pidl("PyObject_Del(self);");
491 $self->pidl("static PyObject *interface_$interface->{NAME}_getattr(PyObject *obj, char *name)");
494 $self->pidl("return Py_FindMethod(interface_$interface->{NAME}\_methods, obj, name);");
500 $self->pidl("PyTypeObject $interface->{NAME}_InterfaceType = {");
502 $self->pidl("PyObject_HEAD_INIT(NULL) 0,");
503 $self->pidl(".tp_name = \"$interface->{NAME}\",");
504 $self->pidl(".tp_basicsize = sizeof($interface->{NAME}_InterfaceObject),");
505 $self->pidl(".tp_dealloc = interface_$interface->{NAME}_dealloc,");
506 $self->pidl(".tp_getattr = interface_$interface->{NAME}_getattr,");
512 $self->register_module_method($interface->{NAME}, "interface_$interface->{NAME}", "METH_VARARGS|METH_KEYWORDS", "NULL");
513 $self->pidl("static PyObject *interface_$interface->{NAME}(PyObject *self, PyObject *args, PyObject *kwargs)");
516 $self->pidl("$interface->{NAME}_InterfaceObject *ret;");
517 $self->pidl("const char *binding_string;");
518 $self->pidl("struct cli_credentials *credentials;");
519 $self->pidl("struct loadparm_context *lp_ctx = NULL;");
520 $self->pidl("PyObject *py_lp_ctx = NULL, *py_credentials = Py_None;");
521 $self->pidl("TALLOC_CTX *mem_ctx = NULL;");
522 $self->pidl("NTSTATUS status;");
524 $self->pidl("const char *kwnames[] = {");
526 $self->pidl("\"binding\", \"lp_ctx\", \"credentials\", NULL");
529 $self->pidl("extern struct loadparm_context *lp_from_py_object(PyObject *py_obj);");
530 $self->pidl("extern struct cli_credentials *cli_credentials_from_py_object(PyObject *py_obj);");
532 $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"sO|O:$interface->{NAME}\", discard_const_p(char *, kwnames), &binding_string, &py_lp_ctx, &py_credentials)) {");
534 $self->pidl("return NULL;");
538 $self->pidl("if (py_lp_ctx != NULL) {");
540 $self->pidl("lp_ctx = lp_from_py_object(py_lp_ctx);");
541 $self->pidl("if (lp_ctx == NULL) {");
543 $self->pidl("PyErr_SetString(PyExc_TypeError, \"Expected loadparm context\");");
544 $self->pidl("return NULL;");
551 $self->pidl("credentials = cli_credentials_from_py_object(py_credentials);");
552 $self->pidl("if (credentials == NULL) {");
554 $self->pidl("PyErr_SetString(PyExc_TypeError, \"Expected credentials\");");
555 $self->pidl("return NULL;");
559 $self->pidl("ret = PyObject_New($interface->{NAME}_InterfaceObject, &$interface->{NAME}_InterfaceType);");
562 $self->pidl("status = dcerpc_pipe_connect(NULL, &ret->pipe, binding_string, ");
563 $self->pidl(" &ndr_table_$interface->{NAME}, credentials, NULL, lp_ctx);");
564 $self->handle_ntstatus("status", "NULL", "mem_ctx");
566 $self->pidl("ret->pipe->conn->flags |= DCERPC_NDR_REF_ALLOC;");
568 $self->pidl("return (PyObject *)ret;");
575 $self->pidl_hdr("\n");
576 $self->pidl_hdr("#endif /* _HEADER_NDR_$interface->{NAME} */\n");
579 sub register_module_method($$$$$)
581 my ($self, $fn_name, $pyfn_name, $flags, $doc) = @_;
583 push (@{$self->{module_methods}}, [$fn_name, $pyfn_name, $flags, $doc])
588 my ($self, $dest, $src) = @_;
589 if ($dest =~ /^\&/) {
590 $self->pidl("memcpy($dest, $src, sizeof(" . get_value_of($dest) . "));");
592 $self->pidl("$dest = $src;");
596 sub ConvertObjectFromPythonData($$$$$$)
598 my ($self, $mem_ctx, $cvar, $ctype, $target, $fail) = @_;
600 die("undef type for $cvar") unless(defined($ctype));
602 $ctype = resolveType($ctype);
604 my $actual_ctype = $ctype;
605 if ($ctype->{TYPE} eq "TYPEDEF") {
606 $actual_ctype = $ctype->{DATA};
609 if ($actual_ctype->{TYPE} eq "ENUM" or $actual_ctype->{TYPE} eq "BITMAP" or
610 $actual_ctype->{TYPE} eq "SCALAR" and (
611 expandAlias($actual_ctype->{NAME}) =~ /^(u?int[0-9]+|hyper|NTTIME|time_t|NTTIME_hyper|NTTIME_1sec|dlong|udlong|udlongr)$/)) {
612 $self->pidl("PY_CHECK_TYPE(PyInt, $cvar, $fail);");
613 $self->pidl("$target = PyInt_AsLong($cvar);");
617 if ($actual_ctype->{TYPE} eq "STRUCT") {
618 $self->pidl("PY_CHECK_TYPE($ctype->{NAME}, $cvar, $fail);");
619 $self->assign($target, "py_talloc_get_ptr($cvar)");
623 if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "DATA_BLOB") {
624 $self->pidl("$target = data_blob_talloc($mem_ctx, PyString_AsString($cvar), PyString_Size($cvar));");
628 if ($actual_ctype->{TYPE} eq "SCALAR" and
629 ($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")) {
630 $self->pidl("$target = talloc_strdup($mem_ctx, PyString_AsString($cvar));");
634 if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "ipv4address") {
635 $self->pidl("$target = PyString_AsString($cvar);");
640 if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "NTSTATUS") {
641 $self->pidl("$target = PyInt_AsLong($cvar);");
645 if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "WERROR") {
646 $self->pidl("$target = PyInt_AsLong($cvar);");
650 if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "string_array") {
651 $self->pidl("$target = PyCObject_AsVoidPtr($cvar);");
655 if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "pointer") {
656 $self->assign($target, "PyCObject_AsVoidPtr($cvar)");
660 die("unknown type ".mapTypeName($ctype) . ": $cvar");
664 sub ConvertObjectFromPythonLevel($$$$$$$$)
666 my ($self, $env, $mem_ctx, $py_var, $e, $l, $var_name, $fail) = @_;
668 if ($l->{TYPE} eq "POINTER") {
669 if ($l->{POINTER_TYPE} ne "ref") {
670 $self->pidl("if ($py_var == Py_None) {");
672 $self->pidl("$var_name = NULL;");
674 $self->pidl("} else {");
677 $self->pidl("$var_name = talloc_ptrtype($mem_ctx, $var_name);");
678 $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, GetNextLevel($e, $l), get_value_of($var_name), $fail);
679 if ($l->{POINTER_TYPE} ne "ref") {
683 } elsif ($l->{TYPE} eq "ARRAY") {
684 if (is_charset_array($e, $l)) {
685 $self->pidl("PY_CHECK_TYPE(PyUnicode, $py_var, $fail);");
686 # FIXME: Use Unix charset setting rather than utf-8
687 $self->pidl(get_pointer_to($var_name) . " = PyString_AsString(PyUnicode_AsEncodedString($py_var, \"utf-8\", \"ignore\"));");
689 my $pl = GetPrevLevel($e, $l);
690 if ($pl && $pl->{TYPE} eq "POINTER") {
691 $var_name = get_pointer_to($var_name);
694 my $counter = "$e->{NAME}_cntr_$l->{LEVEL_INDEX}";
695 $self->pidl("PY_CHECK_TYPE(PyList, $py_var, $fail);");
698 $self->pidl("int $counter;");
699 if (!$l->{IS_FIXED}) {
700 $self->pidl("$var_name = talloc_array_ptrtype($mem_ctx, $var_name, PyList_Size($py_var));");
702 $self->pidl("for ($counter = 0; $counter < PyList_Size($py_var); $counter++) {");
704 $self->ConvertObjectFromPythonLevel($env, $var_name, "PyList_GetItem($py_var, $counter)", $e, GetNextLevel($e, $l), $var_name."[$counter]", $fail);
710 } elsif ($l->{TYPE} eq "DATA") {
712 if (not Parse::Pidl::Typelist::is_scalar($l->{DATA_TYPE})) {
713 $var_name = get_pointer_to($var_name);
715 $self->ConvertObjectFromPythonData($mem_ctx, $py_var, $l->{DATA_TYPE}, $var_name, $fail);
716 } elsif ($l->{TYPE} eq "SWITCH") {
717 $var_name = get_pointer_to($var_name);
718 my $switch = ParseExpr($l->{SWITCH_IS}, $env, $e);
719 $self->assign($var_name, "py_export_" . GetNextLevel($e, $l)->{DATA_TYPE} . "($mem_ctx, $switch, $py_var)");
720 } elsif ($l->{TYPE} eq "SUBCONTEXT") {
721 $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, GetNextLevel($e, $l), $var_name, $fail);
723 die("unknown level type $l->{TYPE}");
727 sub ConvertObjectFromPython($$$$$$$)
729 my ($self, $env, $mem_ctx, $ctype, $cvar, $target, $fail) = @_;
731 $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $cvar, $ctype, $ctype->{LEVELS}[0], $target, $fail);
734 sub ConvertScalarToPython($$$)
736 my ($self, $ctypename, $cvar) = @_;
738 die("expected string for $cvar, not $ctypename") if (ref($ctypename) eq "HASH");
740 $ctypename = expandAlias($ctypename);
742 if ($ctypename =~ /^(int|long|char|u?int[0-9]+|hyper|dlong|udlong|udlongr|time_t|NTTIME_hyper|NTTIME|NTTIME_1sec)$/) {
743 return "PyInt_FromLong($cvar)";
746 if ($ctypename eq "DATA_BLOB") {
747 return "PyString_FromStringAndSize((char *)($cvar).data, ($cvar).length)";
750 if ($ctypename eq "NTSTATUS") {
751 return "PyInt_FromLong(NT_STATUS_V($cvar))";
754 if ($ctypename eq "WERROR") {
755 return "PyInt_FromLong(W_ERROR_V($cvar))";
758 if (($ctypename eq "string" or $ctypename eq "nbt_string" or $ctypename eq "nbt_name" or $ctypename eq "wrepl_nbt_name")) {
759 return "PyString_FromString($cvar)";
763 if ($ctypename eq "string_array") { return "PyCObject_FromVoidPtr($cvar)"; }
764 if ($ctypename eq "ipv4address") { return "PyString_FromString($cvar)"; }
765 if ($ctypename eq "pointer") {
766 return "PyCObject_FromVoidPtr($cvar, talloc_free)";
769 die("Unknown scalar type $ctypename");
772 sub ConvertObjectToPythonData($$$$$)
774 my ($self, $mem_ctx, $ctype, $cvar) = @_;
776 die("undef type for $cvar") unless(defined($ctype));
778 $ctype = resolveType($ctype);
780 my $actual_ctype = $ctype;
781 if ($ctype->{TYPE} eq "TYPEDEF") {
782 $actual_ctype = $ctype->{DATA};
785 if ($actual_ctype->{TYPE} eq "ENUM") {
786 return $self->ConvertScalarToPython(Parse::Pidl::Typelist::enum_type_fn($actual_ctype), $cvar);
787 } elsif ($actual_ctype->{TYPE} eq "BITMAP") {
788 return $self->ConvertScalarToPython(Parse::Pidl::Typelist::bitmap_type_fn($actual_ctype), $cvar);
789 } elsif ($actual_ctype->{TYPE} eq "SCALAR") {
790 return $self->ConvertScalarToPython($actual_ctype->{NAME}, $cvar);
791 } elsif ($actual_ctype->{TYPE} eq "STRUCT") {
792 return "py_talloc_import_ex(&$ctype->{NAME}_Type, $mem_ctx, $cvar)";
795 die("unknown type ".mapTypeName($ctype) . ": $cvar");
798 sub ConvertObjectToPythonLevel($$$$$)
800 my ($self, $mem_ctx, $env, $e, $l, $var_name, $py_var) = @_;
802 if ($l->{TYPE} eq "POINTER") {
803 if ($l->{POINTER_TYPE} ne "ref") {
804 $self->pidl("if ($var_name == NULL) {");
806 $self->pidl("$py_var = Py_None;");
808 $self->pidl("} else {");
811 $self->ConvertObjectToPythonLevel($var_name, $env, $e, GetNextLevel($e, $l), get_value_of($var_name), $py_var);
812 if ($l->{POINTER_TYPE} ne "ref") {
816 } elsif ($l->{TYPE} eq "ARRAY") {
817 if (is_charset_array($e, $l)) {
818 $var_name = get_pointer_to($var_name);
819 # FIXME: Use Unix charset setting rather than utf-8
820 $self->pidl("$py_var = PyUnicode_Decode($var_name, strlen($var_name), \"utf-8\", \"ignore\");");
822 my $pl = GetPrevLevel($e, $l);
823 if ($pl && $pl->{TYPE} eq "POINTER") {
824 $var_name = get_pointer_to($var_name);
827 die("No SIZE_IS for array $var_name") unless (defined($l->{SIZE_IS}));
828 my $length = $l->{SIZE_IS};
829 if (defined($l->{LENGTH_IS})) {
830 $length = $l->{LENGTH_IS};
833 $length = ParseExpr($length, $env, $e);
834 $self->pidl("$py_var = PyList_New($length);");
837 my $counter = "$e->{NAME}_cntr_$l->{LEVEL_INDEX}";
838 $self->pidl("int $counter;");
839 $self->pidl("for ($counter = 0; $counter < $length; $counter++) {");
841 my $member_var = "py_$e->{NAME}_$l->{LEVEL_INDEX}";
842 $self->pidl("PyObject *$member_var;");
843 $self->ConvertObjectToPythonLevel($var_name, $env, $e, GetNextLevel($e, $l), $var_name."[$counter]", $member_var);
844 $self->pidl("PyList_SetItem($py_var, $counter, $member_var);");
850 } elsif ($l->{TYPE} eq "SWITCH") {
851 $var_name = get_pointer_to($var_name);
852 my $switch = ParseExpr($l->{SWITCH_IS}, $env, $e);
853 $self->pidl("$py_var = py_import_" . GetNextLevel($e, $l)->{DATA_TYPE} . "($mem_ctx, $switch, $var_name);");
854 } elsif ($l->{TYPE} eq "DATA") {
855 if (not Parse::Pidl::Typelist::is_scalar($l->{DATA_TYPE})) {
856 $var_name = get_pointer_to($var_name);
858 my $conv = $self->ConvertObjectToPythonData($mem_ctx, $l->{DATA_TYPE}, $var_name);
859 $self->pidl("$py_var = $conv;");
860 } elsif ($l->{TYPE} eq "SUBCONTEXT") {
861 $self->ConvertObjectToPythonLevel($mem_ctx, $env, $e, GetNextLevel($e, $l), $var_name, $py_var);
863 die("Unknown level type $l->{TYPE} $var_name");
867 sub ConvertObjectToPython($$$$$$)
869 my ($self, $mem_ctx, $env, $ctype, $cvar, $py_var) = @_;
871 $self->ConvertObjectToPythonLevel($mem_ctx, $env, $ctype, $ctype->{LEVELS}[0], $cvar, $py_var);
876 my($self,$basename,$ndr,$ndr_hdr,$hdr) = @_;
879 $py_hdr =~ s/ndr_([^\/]+)$/py_$1/g;
881 $self->pidl_hdr("/* header auto-generated by pidl */\n\n");
884 /* Python wrapper functions auto-generated by pidl */
885 #include \"includes.h\"
887 #include \"librpc/rpc/dcerpc.h\"
888 #include \"scripting/python/pytalloc.h\"
890 #include \"$ndr_hdr\"
893 #define PY_CHECK_TYPE(type, var, fail) \\
894 if (!type ## _Check(var)) {\\
895 PyErr_Format(PyExc_TypeError, \"Expected type %s\", type ## _Type.tp_name); \\
900 foreach my $x (@$ndr) {
901 ($x->{TYPE} eq "INTERFACE") && $self->Interface($x, $basename);
902 ($x->{TYPE} eq "IMPORT") && $self->Import(@{$x->{PATHS}});
905 $self->pidl("static PyMethodDef $basename\_methods[] = {");
907 foreach (@{$self->{module_methods}}) {
908 my ($fn_name, $pyfn_name, $flags, $doc) = @$_;
909 $self->pidl("{ \"$fn_name\", (PyCFunction)$pyfn_name, $flags, $doc },");
912 $self->pidl("{ NULL, NULL, 0, NULL }");
918 $self->pidl("void init$basename(void)");
921 $self->pidl("PyObject *m;");
922 $self->pidl("m = Py_InitModule(\"$basename\", $basename\_methods);");
923 foreach my $name (keys %{$self->{constants}}) {
925 my ($ctype, $cvar) = @{$self->{constants}->{$name}};
926 if ($cvar =~ /^[0-9]+$/ or $cvar =~ /^0x[0-9a-fA-F]+$/) {
927 $py_obj = "PyInt_FromLong($cvar)";
928 } elsif ($cvar =~ /^".*"$/) {
929 $py_obj = "PyString_FromString($cvar)";
931 $py_obj = $self->ConvertObjectToPythonData("NULL", $ctype, $cvar);
934 $self->pidl("PyModule_AddObject(m, \"$name\", $py_obj);");
938 return ($self->{res_hdr}, $self->{res});