From 57539c84416aeb8fc8e3a8653f790b329e6fa9a1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 12 Sep 2016 09:20:44 +0200 Subject: pidl:Python: add PyTypeObject objects for function structs They provide get/set methods for the in_* and out_* elements and the magic __ndr_{push,pull,print}_{in,out}__ hooks to enable the marshalling via ndr_{push,pull,print}_{in,out}(). This provides an easy way to generate and parse the payload of DCERPC requests and responses, which is very useful for writing tests. Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider --- pidl/lib/Parse/Pidl/Samba4/Python.pm | 478 ++++++++++++++++++++++++++++++++++- 1 file changed, 477 insertions(+), 1 deletion(-) (limited to 'pidl') diff --git a/pidl/lib/Parse/Pidl/Samba4/Python.pm b/pidl/lib/Parse/Pidl/Samba4/Python.pm index cab51d11c00..5edf96c5993 100644 --- a/pidl/lib/Parse/Pidl/Samba4/Python.pm +++ b/pidl/lib/Parse/Pidl/Samba4/Python.pm @@ -12,7 +12,7 @@ use strict; use Parse::Pidl qw(warning fatal error); use Parse::Pidl::Typelist qw(hasType resolveType getType mapTypeName expandAlias bitmap_type_fn enum_type_fn); use Parse::Pidl::Util qw(has_property ParseExpr unmake_str); -use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred ContainsPipe is_charset_array); +use Parse::Pidl::NDR qw(ReturnTypeElement GetPrevLevel GetNextLevel ContainsDeferred ContainsPipe is_charset_array); use Parse::Pidl::CUtil qw(get_value_of get_pointer_to); use Parse::Pidl::Samba4 qw(ArrayDynamicallyAllocated); use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv); @@ -409,6 +409,479 @@ sub PythonStruct($$$$$$) return "&$typeobject"; } +sub PythonFunctionStruct($$$$) +{ + my ($self, $modulename, $fn, $iface, $prettyname) = @_; + + my $inenv = GenerateFunctionInEnv($fn, "object->"); + my $outenv = GenerateFunctionOutEnv($fn, "object->"); + + my $name = "$fn->{NAME}"; + my $cname = "struct $name"; + + $self->pidl(""); + + my $getsetters = "NULL"; + + foreach my $e (@{$fn->{ELEMENTS}}) { + if (grep(/in/,@{$e->{DIRECTION}})) { + my $inname = "$name\_in"; + my $ename = "in.$e->{NAME}"; + $self->PythonElementGetSet($inname, $cname, $ename, $e, $inenv); + } + if (grep(/out/,@{$e->{DIRECTION}})) { + my $outname = "$name\_out"; + my $ename = "out.$e->{NAME}"; + $self->PythonElementGetSet($outname, $cname, $ename, $e, $outenv); + } + } + + if (defined($fn->{RETURN_TYPE})) { + my $e = ReturnTypeElement($fn); + my $ename = "out.result"; + $self->PythonElementGetSet($name, $cname, $ename, $e, $outenv); + } + + $getsetters = "py_$name\_getsetters"; + $self->pidl("static PyGetSetDef ".$getsetters."[] = {"); + $self->indent; + foreach my $e (@{$fn->{ELEMENTS}}) { + if (grep(/in/,@{$e->{DIRECTION}})) { + $self->pidl("{"); + $self->indent; + $self->pidl(".name = discard_const_p(char, \"in_$e->{NAME}\"),"); + $self->pidl(".get = py_$name\_in_get_$e->{NAME},"); + $self->pidl(".set = py_$name\_in_set_$e->{NAME},"); + $self->pidl(".doc = discard_const_p(char, \"PIDL-generated element of base type $e->{TYPE}\")"); + $self->deindent; + $self->pidl("},"); + } + if (grep(/out/,@{$e->{DIRECTION}})) { + $self->pidl("{"); + $self->indent; + $self->pidl(".name = discard_const_p(char, \"out_$e->{NAME}\"),"); + $self->pidl(".get = py_$name\_out_get_$e->{NAME},"); + $self->pidl(".set = py_$name\_out_set_$e->{NAME},"); + $self->pidl(".doc = discard_const_p(char, \"PIDL-generated element of base type $e->{TYPE}\")"); + $self->deindent; + $self->pidl("},"); + } + } + if (defined($fn->{RETURN_TYPE})) { + $self->pidl("{"); + $self->indent; + $self->pidl(".name = discard_const_p(char, \"result\"),"); + $self->pidl(".get = py_$name\_get_result,"); + $self->pidl(".set = py_$name\_set_result,"); + $self->pidl(".doc = discard_const_p(char, \"PIDL-generated element of type $fn->{RETURN_TYPE}\")"); + $self->deindent; + $self->pidl("},"); + } + $self->pidl("{ .name = NULL }"); + $self->deindent; + $self->pidl("};"); + $self->pidl(""); + + $self->pidl("static PyObject *py_$name\_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)"); + $self->pidl("{"); + $self->indent; + $self->pidl("return pytalloc_new($cname, type);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + my $py_methods = "NULL"; + + my $ndr_call = "const struct ndr_interface_call *call = NULL;"; + my $object_ptr = "$cname *object = ($cname *)pytalloc_get_ptr(py_obj);"; + + $self->pidl("static PyObject *py_$name\_ndr_opnum(PyTypeObject *type)"); + $self->pidl("{"); + $self->indent; + $self->pidl(""); + $self->pidl(""); + $self->pidl("return PyInt_FromLong($fn->{OPNUM});"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("static PyObject *py_$name\_ndr_pack(PyObject *py_obj, int ndr_inout_flags, uint32_t ndr_push_flags)"); + $self->pidl("{"); + $self->indent; + $self->pidl("$ndr_call"); + $self->pidl("$object_ptr"); + $self->pidl("PyObject *ret = NULL;"); + $self->pidl("struct ndr_push *push = NULL;"); + $self->pidl("DATA_BLOB blob;"); + $self->pidl("enum ndr_err_code err;"); + $self->pidl(""); + $self->pidl("if (ndr_table_$iface\.num_calls < $fn->{OPNUM}) {"); + $self->indent; + $self->pidl("PyErr_SetString(PyExc_TypeError, \"Internal Error, ndr_interface_call missing for py_$name\_ndr_pack\");"); + $self->pidl("return NULL;"); + $self->deindent; + $self->pidl("}"); + $self->pidl("call = &ndr_table_$iface\.calls[$fn->{OPNUM}];"); + $self->pidl(""); + $self->pidl("push = ndr_push_init_ctx(pytalloc_get_mem_ctx(py_obj));"); + $self->pidl("if (push == NULL) {"); + $self->indent; + $self->pidl("PyErr_SetNdrError(NDR_ERR_ALLOC);"); + $self->pidl("return NULL;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + $self->pidl("push->flags |= ndr_push_flags;"); + $self->pidl(""); + $self->pidl("err = call->ndr_push(push, ndr_inout_flags, object);"); + $self->pidl("if (!NDR_ERR_CODE_IS_SUCCESS(err)) {"); + $self->indent; + $self->pidl("TALLOC_FREE(push);"); + $self->pidl("PyErr_SetNdrError(err);"); + $self->pidl("return NULL;"); + $self->deindent; + $self->pidl("}"); + $self->pidl("blob = ndr_push_blob(push);"); + $self->pidl("ret = PyString_FromStringAndSize((char *)blob.data, blob.length);"); + $self->pidl("TALLOC_FREE(push);"); + $self->pidl("return ret;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("static PyObject *py_$name\_ndr_pack_in(PyObject *py_obj, PyObject *args, PyObject *kwargs)"); + $self->pidl("{"); + $self->indent; + $self->pidl("const char * const kwnames[] = { \"bigendian\", \"ndr64\", NULL };"); + $self->pidl("PyObject *bigendian_obj = NULL;"); + $self->pidl("PyObject *ndr64_obj = NULL;"); + $self->pidl("uint32_t ndr_push_flags = 0;"); + $self->pidl(""); + $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"|OO:__ndr_pack_in__\","); + $self->indent; + $self->pidl("discard_const_p(char *, kwnames),"); + $self->pidl("&bigendian_obj,"); + $self->pidl("&ndr64_obj)) {"); + $self->deindent; + $self->indent; + $self->pidl("return NULL;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + $self->pidl("if (bigendian_obj && PyObject_IsTrue(bigendian_obj)) {"); + $self->indent; + $self->pidl("ndr_push_flags |= LIBNDR_FLAG_BIGENDIAN;"); + $self->deindent; + $self->pidl("}"); + $self->pidl("if (ndr64_obj && PyObject_IsTrue(ndr64_obj)) {"); + $self->indent; + $self->pidl("ndr_push_flags |= LIBNDR_FLAG_NDR64;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + $self->pidl("return py_$name\_ndr_pack(py_obj, NDR_IN, ndr_push_flags);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("static PyObject *py_$name\_ndr_pack_out(PyObject *py_obj, PyObject *args, PyObject *kwargs)"); + $self->pidl("{"); + $self->indent; + $self->pidl("const char * const kwnames[] = { \"bigendian\", \"ndr64\", NULL };"); + $self->pidl("PyObject *bigendian_obj = NULL;"); + $self->pidl("PyObject *ndr64_obj = NULL;"); + $self->pidl("uint32_t ndr_push_flags = 0;"); + $self->pidl(""); + $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"|OO:__ndr_pack_out__\","); + $self->indent; + $self->pidl("discard_const_p(char *, kwnames),"); + $self->pidl("&bigendian_obj,"); + $self->pidl("&ndr64_obj)) {"); + $self->deindent; + $self->indent; + $self->pidl("return NULL;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + $self->pidl("if (bigendian_obj && PyObject_IsTrue(bigendian_obj)) {"); + $self->indent; + $self->pidl("ndr_push_flags |= LIBNDR_FLAG_BIGENDIAN;"); + $self->deindent; + $self->pidl("}"); + $self->pidl("if (ndr64_obj && PyObject_IsTrue(ndr64_obj)) {"); + $self->indent; + $self->pidl("ndr_push_flags |= LIBNDR_FLAG_NDR64;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + $self->pidl("return py_$name\_ndr_pack(py_obj, NDR_OUT, ndr_push_flags);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("static PyObject *py_$name\_ndr_unpack(PyObject *py_obj, const DATA_BLOB *blob, int ndr_inout_flags, uint32_t ndr_pull_flags, bool allow_remaining)"); + $self->pidl("{"); + $self->indent; + $self->pidl("$ndr_call"); + $self->pidl("$object_ptr"); + $self->pidl("struct ndr_pull *pull = NULL;"); + $self->pidl("enum ndr_err_code err;"); + $self->pidl(""); + $self->pidl("if (ndr_table_$iface\.num_calls < $fn->{OPNUM}) {"); + $self->indent; + $self->pidl("PyErr_SetString(PyExc_TypeError, \"Internal Error, ndr_interface_call missing for py_$name\_ndr_unpack\");"); + $self->pidl("return NULL;"); + $self->deindent; + $self->pidl("}"); + $self->pidl("call = &ndr_table_$iface\.calls[$fn->{OPNUM}];"); + $self->pidl(""); + $self->pidl("pull = ndr_pull_init_blob(blob, object);"); + $self->pidl("if (pull == NULL) {"); + $self->indent; + $self->pidl("PyErr_SetNdrError(NDR_ERR_ALLOC);"); + $self->pidl("return NULL;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + $self->pidl("pull->flags |= ndr_pull_flags;"); + $self->pidl(""); + $self->pidl("err = call->ndr_pull(pull, ndr_inout_flags, object);"); + $self->pidl("if (!NDR_ERR_CODE_IS_SUCCESS(err)) {"); + $self->indent; + $self->pidl("TALLOC_FREE(pull);"); + $self->pidl("PyErr_SetNdrError(err);"); + $self->pidl("return NULL;"); + $self->deindent; + $self->pidl("}"); + $self->pidl("if (!allow_remaining) {"); + $self->indent; + $self->pidl("uint32_t highest_ofs;"); + $self->pidl(""); + $self->pidl("if (pull->offset > pull->relative_highest_offset) {"); + $self->indent; + $self->pidl("highest_ofs = pull->offset;"); + $self->deindent; + $self->pidl("} else {"); + $self->indent; + $self->pidl("highest_ofs = pull->relative_highest_offset;"); + $self->deindent; + $self->pidl("}"); + $self->pidl("if (highest_ofs < pull->data_size) {"); + $self->indent; + $self->pidl("err = ndr_pull_error(pull, NDR_ERR_UNREAD_BYTES,"); + $self->indent; + $self->pidl("\"not all bytes consumed ofs[%u] size[%u]\","); + $self->pidl("highest_ofs, pull->data_size);"); + $self->deindent; + $self->pidl("TALLOC_FREE(pull);"); + $self->pidl("PyErr_SetNdrError(err);"); + $self->pidl("return NULL;"); + $self->deindent; + $self->pidl("}"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + $self->pidl("TALLOC_FREE(pull);"); + $self->pidl("Py_RETURN_NONE;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("static PyObject *py_$name\_ndr_unpack_in(PyObject *py_obj, PyObject *args, PyObject *kwargs)"); + $self->pidl("{"); + $self->indent; + $self->pidl("DATA_BLOB blob;"); + $self->pidl("Py_ssize_t blob_length = 0;"); + $self->pidl("const char * const kwnames[] = { \"data_blob\", \"bigendian\", \"ndr64\", \"allow_remaining\", NULL };"); + $self->pidl("PyObject *bigendian_obj = NULL;"); + $self->pidl("PyObject *ndr64_obj = NULL;"); + $self->pidl("uint32_t ndr_pull_flags = LIBNDR_FLAG_REF_ALLOC;"); + $self->pidl("PyObject *allow_remaining_obj = NULL;"); + $self->pidl("bool allow_remaining = false;"); + $self->pidl(""); + $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"s#|OOO:__ndr_unpack_in__\","); + $self->indent; + $self->pidl("discard_const_p(char *, kwnames),"); + $self->pidl("&blob.data, &blob_length,"); + $self->pidl("&bigendian_obj,"); + $self->pidl("&ndr64_obj,"); + $self->pidl("&allow_remaining_obj)) {"); + $self->deindent; + $self->indent; + $self->pidl("return NULL;"); + $self->deindent; + $self->pidl("}"); + $self->pidl("blob.length = blob_length;"); + $self->pidl(""); + $self->pidl("if (bigendian_obj && PyObject_IsTrue(bigendian_obj)) {"); + $self->indent; + $self->pidl("ndr_pull_flags |= LIBNDR_FLAG_BIGENDIAN;"); + $self->deindent; + $self->pidl("}"); + $self->pidl("if (ndr64_obj && PyObject_IsTrue(ndr64_obj)) {"); + $self->indent; + $self->pidl("ndr_pull_flags |= LIBNDR_FLAG_NDR64;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + $self->pidl("if (allow_remaining_obj && PyObject_IsTrue(allow_remaining_obj)) {"); + $self->indent; + $self->pidl("allow_remaining = true;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + $self->pidl("return py_$name\_ndr_unpack(py_obj, &blob, NDR_IN, ndr_pull_flags, allow_remaining);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("static PyObject *py_$name\_ndr_unpack_out(PyObject *py_obj, PyObject *args, PyObject *kwargs)"); + $self->pidl("{"); + $self->indent; + $self->pidl("DATA_BLOB blob;"); + $self->pidl("Py_ssize_t blob_length = 0;"); + $self->pidl("const char * const kwnames[] = { \"data_blob\", \"bigendian\", \"ndr64\", \"allow_remaining\", NULL };"); + $self->pidl("PyObject *bigendian_obj = NULL;"); + $self->pidl("PyObject *ndr64_obj = NULL;"); + $self->pidl("uint32_t ndr_pull_flags = LIBNDR_FLAG_REF_ALLOC;"); + $self->pidl("PyObject *allow_remaining_obj = NULL;"); + $self->pidl("bool allow_remaining = false;"); + $self->pidl(""); + $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"s#|OOO:__ndr_unpack_out__\","); + $self->indent; + $self->pidl("discard_const_p(char *, kwnames),"); + $self->pidl("&blob.data, &blob_length,"); + $self->pidl("&bigendian_obj,"); + $self->pidl("&ndr64_obj,"); + $self->pidl("&allow_remaining_obj)) {"); + $self->deindent; + $self->indent; + $self->pidl("return NULL;"); + $self->deindent; + $self->pidl("}"); + $self->pidl("blob.length = blob_length;"); + $self->pidl(""); + $self->pidl("if (bigendian_obj && PyObject_IsTrue(bigendian_obj)) {"); + $self->indent; + $self->pidl("ndr_pull_flags |= LIBNDR_FLAG_BIGENDIAN;"); + $self->deindent; + $self->pidl("}"); + $self->pidl("if (ndr64_obj && PyObject_IsTrue(ndr64_obj)) {"); + $self->indent; + $self->pidl("ndr_pull_flags |= LIBNDR_FLAG_NDR64;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + $self->pidl("if (allow_remaining_obj && PyObject_IsTrue(allow_remaining_obj)) {"); + $self->indent; + $self->pidl("allow_remaining = true;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + $self->pidl("return py_$name\_ndr_unpack(py_obj, &blob, NDR_OUT, ndr_pull_flags, allow_remaining);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("static PyObject *py_$name\_ndr_print(PyObject *py_obj, const char *name, int ndr_inout_flags)"); + $self->pidl("{"); + $self->indent; + $self->pidl("$ndr_call"); + $self->pidl("$object_ptr"); + $self->pidl("PyObject *ret;"); + $self->pidl("char *retstr;"); + $self->pidl(""); + $self->pidl("if (ndr_table_$iface\.num_calls < $fn->{OPNUM}) {"); + $self->indent; + $self->pidl("PyErr_SetString(PyExc_TypeError, \"Internal Error, ndr_interface_call missing for py_$name\_ndr_print\");"); + $self->pidl("return NULL;"); + $self->deindent; + $self->pidl("}"); + $self->pidl("call = &ndr_table_$iface\.calls[$fn->{OPNUM}];"); + $self->pidl(""); + $self->pidl("retstr = ndr_print_function_string(pytalloc_get_mem_ctx(py_obj), call->ndr_print, name, ndr_inout_flags, object);"); + $self->pidl("ret = PyString_FromString(retstr);"); + $self->pidl("TALLOC_FREE(retstr);"); + $self->pidl(""); + $self->pidl("return ret;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("static PyObject *py_$name\_ndr_print_in(PyObject *py_obj)"); + $self->pidl("{"); + $self->indent; + $self->pidl("return py_$name\_ndr_print(py_obj, \"$name\_in\", NDR_IN);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("static PyObject *py_$name\_ndr_print_out(PyObject *py_obj)"); + $self->pidl("{"); + $self->indent; + $self->pidl("return py_$name\_ndr_print(py_obj, \"$name\_out\", NDR_OUT);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $py_methods = "py_$name\_methods"; + $self->pidl("static PyMethodDef $py_methods\[] = {"); + $self->indent; + $self->pidl("{ \"opnum\", (PyCFunction)py_$name\_ndr_opnum, METH_NOARGS|METH_CLASS,"); + $self->indent; + $self->pidl("\"$modulename.$prettyname.opnum() -> ".sprintf("%d (0x%02x)", $fn->{OPNUM}, $fn->{OPNUM})." \" },"); + $self->deindent; + $self->pidl("{ \"__ndr_pack_in__\", (PyCFunction)py_$name\_ndr_pack_in, METH_VARARGS|METH_KEYWORDS,"); + $self->indent; + $self->pidl("\"S.ndr_pack_in(object, bigendian=False, ndr64=False) -> blob\\nNDR pack input\" },"); + $self->deindent; + $self->pidl("{ \"__ndr_pack_out__\", (PyCFunction)py_$name\_ndr_pack_out, METH_VARARGS|METH_KEYWORDS,"); + $self->indent; + $self->pidl("\"S.ndr_pack_out(object, bigendian=False, ndr64=False) -> blob\\nNDR pack output\" },"); + $self->deindent; + $self->pidl("{ \"__ndr_unpack_in__\", (PyCFunction)py_$name\_ndr_unpack_in, METH_VARARGS|METH_KEYWORDS,"); + $self->indent; + $self->pidl("\"S.ndr_unpack_in(class, blob, bigendian=False, ndr64=False, allow_remaining=False) -> None\\nNDR unpack input\" },"); + $self->deindent; + $self->pidl("{ \"__ndr_unpack_out__\", (PyCFunction)py_$name\_ndr_unpack_out, METH_VARARGS|METH_KEYWORDS,"); + $self->indent; + $self->pidl("\"S.ndr_unpack_out(class, blob, bigendian=False, ndr64=False, allow_remaining=False) -> None\\nNDR unpack output\" },"); + $self->deindent; + $self->pidl("{ \"__ndr_print_in__\", (PyCFunction)py_$name\_ndr_print_in, METH_NOARGS, \"S.ndr_print_in(object) -> None\\nNDR print input\" },"); + $self->pidl("{ \"__ndr_print_out__\", (PyCFunction)py_$name\_ndr_print_out, METH_NOARGS, \"S.ndr_print_out(object) -> None\\nNDR print output\" },"); + $self->pidl("{ NULL, NULL, 0, NULL }"); + $self->deindent; + $self->pidl("};"); + $self->pidl(""); + + $self->pidl_hdr("static PyTypeObject $name\_Type;\n"); + $self->pidl(""); + my $docstring = $self->DocString($fn, $name); + my $typeobject = "$name\_Type"; + $self->pidl("static PyTypeObject $typeobject = {"); + $self->indent; + $self->pidl("PyObject_HEAD_INIT(NULL) 0,"); + $self->pidl(".tp_name = \"$modulename.$prettyname\","); + $self->pidl(".tp_getset = $getsetters,"); + if ($docstring) { + $self->pidl(".tp_doc = $docstring,"); + } + $self->pidl(".tp_methods = $py_methods,"); + $self->pidl(".tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,"); + $self->pidl(".tp_new = py_$name\_new,"); + $self->deindent; + $self->pidl("};"); + + $self->pidl(""); + + my $talloc_typename = $self->import_type_variable("talloc", "BaseObject"); + $self->register_module_prereadycode(["$name\_Type.tp_base = $talloc_typename;", + "$name\_Type.tp_basicsize = pytalloc_BaseObject_size();", + ""]); + + return "&$typeobject"; +} + sub get_metadata_var($) { my ($e) = @_; @@ -962,6 +1435,9 @@ sub Interface($$$) $prettyname =~ s/^$interface->{NAME}_//; $prettyname =~ s/^$basename\_//; + my $typeobject = $self->PythonFunctionStruct($basename, $d, $interface->{NAME}, $prettyname); + $self->register_module_typeobject($prettyname, $typeobject, $d->{ORIGINAL}); + my ($infn, $outfn, $fndocstring) = $self->PythonFunction($d, $interface->{NAME}, $prettyname); push (@fns, [$infn, $outfn, "dcerpc_$d->{NAME}_r", $prettyname, $fndocstring, $d->{OPNUM}]); -- cgit v1.2.1