]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
Trim the size of the Python bindings a bit.
authorJelmer Vernooij <jelmer@samba.org>
Sun, 25 May 2008 21:14:48 +0000 (23:14 +0200)
committerJelmer Vernooij <jelmer@samba.org>
Sun, 25 May 2008 21:14:48 +0000 (23:14 +0200)
source/librpc/rpc/dcerpc.h
source/librpc/rpc/pyrpc.c
source/librpc/rpc/pyrpc.h
source/pidl/lib/Parse/Pidl/Samba4/Python.pm

index ca6311a4fc2f5f735e4fe87470d993708d27b171..487f9f2edabe679ea945644ee09d396d47f69464 100644 (file)
@@ -370,5 +370,6 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
                        DATA_BLOB *stub_data_in,
                        DATA_BLOB *stub_data_out);
 
+typedef NTSTATUS (*dcerpc_call_fn) (struct dcerpc_pipe *, TALLOC_CTX *, void *);
 
 #endif /* __DCERPC_H__ */
index 26242e8235a6be9ca82c110cbbced754d6ae66ad..b04ca0be3009cc13182ac3b1015c7d425f1e9cce 100644 (file)
 #include "librpc/rpc/dcerpc.h"
 #include "lib/events/events.h"
 
+typedef struct dcerpc_FunctionObject {
+       PyObject_HEAD
+       struct PyNdrRpcMethodDef *method_def;
+} dcerpc_FunctionObject;
+
+static PyMemberDef dcerpc_function_members[] = {
+       { discard_const_p(char, "__opnum__"), T_LONG, 
+         offsetof(struct dcerpc_FunctionObject, method_def), 0,
+         discard_const_p(char, "opnum") },
+       { NULL }
+};
+
+
+static PyObject * dcerpc_function_ndr_pack_in(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+       /* FIXME */
+       return Py_None;
+}
+
+static PyMethodDef dcerpc_function_methods[] = {
+       { "__ndr_pack_in__", (PyCFunction)dcerpc_function_ndr_pack_in, METH_VARARGS|METH_KEYWORDS, NULL },
+       { NULL, NULL, 0, NULL },
+};
+
+PyTypeObject dcerpc_FunctionType = {
+       PyObject_HEAD_INIT(NULL) 0,
+       .tp_name = "dcerpc.Function",
+       .tp_basicsize = sizeof(dcerpc_FunctionObject),
+       .tp_members = dcerpc_function_members,
+       .tp_methods = dcerpc_function_methods,
+       .tp_flags = Py_TPFLAGS_DEFAULT,
+};
+
+PyObject *py_dcerpc_call_wrapper(PyObject *self, PyObject *args, void *wrapped, PyObject *kwargs)
+{      
+       dcerpc_InterfaceObject *iface = (dcerpc_InterfaceObject *)self;
+       struct PyNdrRpcMethodDef *md = wrapped;
+       TALLOC_CTX *mem_ctx;
+       NTSTATUS status;
+       void *r;
+       PyObject *result = Py_None;
+
+       if (md->pack_in_data == NULL || md->unpack_out_data == NULL) {
+               PyErr_SetString(PyExc_NotImplementedError, "No marshalling code available yet");
+               return NULL;
+       }
+
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL)
+               return NULL;
+
+       r = talloc_zero_size(mem_ctx, md->table->calls[md->opnum].struct_size);
+       if (r == NULL)
+               return NULL;
+
+       if (!md->pack_in_data(args, kwargs, r)) {
+               talloc_free(mem_ctx);
+               return NULL;
+       }
+
+       status = md->call(iface->pipe, mem_ctx, r);
+       if (NT_STATUS_IS_ERR(status)) {
+               PyErr_SetDCERPCStatus(iface->pipe, status);
+               talloc_free(mem_ctx);
+               return NULL;
+       }
+
+       result = md->unpack_out_data(r);
+
+       talloc_free(mem_ctx);
+       return result;
+}
+
+
+PyObject *PyDescr_NewNdrRpcMethod(PyTypeObject *ifacetype, struct PyNdrRpcMethodDef *md)
+{
+       struct wrapperbase *wb = calloc(sizeof(struct wrapperbase), 1);
+
+       wb->name = md->name;
+       wb->flags = PyWrapperFlag_KEYWORDS;
+       wb->wrapper = py_dcerpc_call_wrapper;
+       wb->doc = md->doc;
+       
+       return PyDescr_NewWrapper(ifacetype, wb, md);
+}
+
+bool PyInterface_AddNdrRpcMethods(PyTypeObject *ifacetype, struct PyNdrRpcMethodDef *mds)
+{
+       int i;
+       for (i = 0; mds[i].name; i++) {
+               PyDict_SetItemString(ifacetype->tp_dict, mds[i].name, 
+                                    PyDescr_NewNdrRpcMethod(ifacetype, &mds[i]));
+       }
+
+       return true;
+}
+
 static bool PyString_AsGUID(PyObject *object, struct GUID *uuid)
 {
        NTSTATUS status;
@@ -311,7 +408,6 @@ static PyObject *dcerpc_interface_new(PyTypeObject *self, PyObject *args, PyObje
                talloc_free(mem_ctx);
                return NULL;
        }
-
        ret->pipe->conn->flags |= DCERPC_NDR_REF_ALLOC;
        return (PyObject *)ret;
 }
@@ -341,6 +437,9 @@ void initbase(void)
        if (PyType_Ready(&dcerpc_InterfaceType) < 0)
                return;
 
+       if (PyType_Ready(&dcerpc_FunctionType) < 0)
+               return;
+
        m = Py_InitModule3("base", NULL, "DCE/RPC protocol implementation");
        if (m == NULL)
                return;
index 209d7d3f1f8f4a3dc95cbbcfa853819a6113c9c3..5ec9c6ed838eba71ac0b3e3fcc90cc9b86aad718 100644 (file)
@@ -52,4 +52,20 @@ PyAPI_DATA(PyTypeObject) dcerpc_InterfaceType;
 
 void PyErr_SetDCERPCStatus(struct dcerpc_pipe *pipe, NTSTATUS status);
 
+typedef bool (*py_data_pack_fn) (PyObject *args, PyObject *kwargs, void *r);
+typedef PyObject *(*py_data_unpack_fn) (void *r);
+
+struct PyNdrRpcMethodDef {
+       const char *name;
+       const char *doc;
+       dcerpc_call_fn call;
+       py_data_pack_fn pack_in_data;
+       py_data_unpack_fn unpack_out_data;
+       uint32_t opnum;
+       const struct ndr_interface_table *table;
+};
+
+bool PyInterface_AddNdrRpcMethods(PyTypeObject *object, struct PyNdrRpcMethodDef *mds);
+PyObject *PyDescr_NewNdrRpcMethod(PyTypeObject *type, struct PyNdrRpcMethodDef *md);
+
 #endif /* _PYRPC_H_ */
index 720d066360f309c5433f9a1fab9a584c2795b883..0832401d7d388ebacd54c8542c3bdaabd2d4f75e 100644 (file)
@@ -21,7 +21,8 @@ $VERSION = '0.01';
 sub new($) {
        my ($class) = @_;
        my $self = { res => "", res_hdr => "", tabs => "", constants => {},
-                    module_methods => [], module_objects => [], module_types => []};
+                    module_methods => [], module_objects => [], module_types => [],
+                                readycode => [] };
        bless($self, $class);
 }
 
@@ -341,41 +342,6 @@ sub find_metadata_args($)
        return $metadata_args;
 }
 
-sub PythonFunctionBody($$$$$)
-{
-       my ($self, $fn, $iface, $prettyname, $infn, $outfn) = @_;
-
-       $self->pidl("dcerpc_InterfaceObject *iface = (dcerpc_InterfaceObject *)self;");
-       $self->pidl("NTSTATUS status;");
-       $self->pidl("TALLOC_CTX *mem_ctx = talloc_new(NULL);");
-       $self->pidl("struct $fn->{NAME} *r = talloc_zero(mem_ctx, struct $fn->{NAME});");
-       $self->pidl("PyObject *result = Py_None;");
-       
-       $self->pidl("if (!$infn(args, kwargs, r)) {");
-       $self->indent;
-       $self->pidl("talloc_free(mem_ctx);");
-       $self->pidl("return NULL;");
-       $self->deindent;
-       $self->pidl("}");
-       $self->pidl("");
-
-       $self->pidl("status = dcerpc_$fn->{NAME}(iface->pipe, mem_ctx, r);");
-       $self->pidl("if (NT_STATUS_IS_ERR(status)) {");
-       $self->indent;
-       $self->pidl("PyErr_SetDCERPCStatus(iface->pipe, status);");
-       $self->pidl("talloc_free(mem_ctx);");
-       $self->pidl("return NULL;");
-       $self->deindent;
-       $self->pidl("}");
-       $self->pidl("");
-
-       $self->pidl("result = $outfn(r);");
-       $self->pidl("");
-       $self->pidl("talloc_free(mem_ctx);");
-       $self->pidl("return result;");
-
-}
-
 sub PythonFunctionUnpackOut($$$)
 {
        my ($self, $fn, $fnname) = @_;
@@ -453,6 +419,7 @@ sub PythonFunctionUnpackOut($$$)
        $self->pidl("return result;");
        $self->deindent;
        $self->pidl("}");
+       $self->pidl("");
 
        return ($outfnname, $signature);
 }
@@ -535,20 +502,13 @@ sub PythonFunction($$$)
        my ($insignature, $outsignature);
        my ($infn, $outfn);
 
-       if (not has_property($fn, "todo")) {
-               ($infn, $insignature) = $self->PythonFunctionPackIn($fn, $fnname);
-               ($outfn, $outsignature) = $self->PythonFunctionUnpackOut($fn, $fnname);
-       }
-
-       $self->pidl("static PyObject *$fnname(PyObject *self, PyObject *args, PyObject *kwargs)");
-       $self->pidl("{");
-       $self->indent;
        if (has_property($fn, "todo")) {
-               $self->pidl("PyErr_SetString(PyExc_NotImplementedError, \"No marshalling code available yet for $prettyname\");");
-               $self->pidl("return NULL;");
                unless ($docstring) { $docstring = "NULL"; }
+               $infn = "NULL";
+               $outfn = "NULL";
        } else {
-               $self->PythonFunctionBody($fn, $iface, $prettyname, $infn, $outfn);
+               ($infn, $insignature) = $self->PythonFunctionPackIn($fn, $fnname);
+               ($outfn, $outsignature) = $self->PythonFunctionUnpackOut($fn, $fnname);
                my $signature = "S.$prettyname($insignature) -> $outsignature";
                if ($docstring) {
                        $docstring = "\"$signature\\n\\n\"$docstring";
@@ -557,11 +517,7 @@ sub PythonFunction($$$)
                }
        }
 
-       $self->deindent;
-       $self->pidl("}");
-       $self->pidl("");
-
-       return ($fnname, $docstring);
+       return ($infn, $outfn, $docstring);
 }
 
 sub handle_werror($$$$)
@@ -689,18 +645,18 @@ sub Interface($$$)
                        $prettyname =~ s/^$interface->{NAME}_//;
                        $prettyname =~ s/^$basename\_//;
 
-                       my ($fnname, $fndocstring) = $self->PythonFunction($d, $interface->{NAME}, $prettyname);
+                       my ($infn, $outfn, $fndocstring) = $self->PythonFunction($d, $interface->{NAME}, $prettyname);
 
-                       push (@fns, [$fnname, $prettyname, $fndocstring]);
+                       push (@fns, [$infn, $outfn, "dcerpc_$d->{NAME}", $prettyname, $fndocstring, $d->{OPNUM}]);
                }
 
-               $self->pidl("static PyMethodDef interface_$interface->{NAME}\_methods[] = {");
+               $self->pidl("static struct PyNdrRpcMethodDef interface_$interface->{NAME}\_methods[] = {");
                $self->indent;
                foreach my $d (@fns) {
-                       my ($c_fn, $prettyname, $docstring) = @$d;
-                       $self->pidl("{ \"$prettyname\", (PyCFunction)$c_fn, METH_VARARGS|METH_KEYWORDS, $docstring },");
+                       my ($infn, $outfn, $callfn, $prettyname, $docstring, $opnum) = @$d;
+                       $self->pidl("{ \"$prettyname\", $docstring, (dcerpc_call_fn)$callfn, (py_data_pack_fn)$infn, (py_data_unpack_fn)$outfn, $opnum, &ndr_table_$interface->{NAME} },");
                }
-               $self->pidl("{ NULL, NULL, 0, NULL }");
+               $self->pidl("{ NULL }");
                $self->deindent;
                $self->pidl("};");
                $self->pidl("");
@@ -806,7 +762,6 @@ sub Interface($$$)
                $self->pidl(".tp_name = \"$basename.$interface->{NAME}\",");
                $self->pidl(".tp_basicsize = sizeof(dcerpc_InterfaceObject),");
                $self->pidl(".tp_base = &dcerpc_InterfaceType,");
-               $self->pidl(".tp_methods = interface_$interface->{NAME}_methods,");
                $self->pidl(".tp_doc = $docstring,");
                $self->pidl(".tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,");
                $self->pidl(".tp_new = interface_$interface->{NAME}_new,");
@@ -816,6 +771,7 @@ sub Interface($$$)
                $self->pidl("");
 
                $self->register_module_typeobject($interface->{NAME}, "&$interface->{NAME}_InterfaceType");
+               $self->register_module_readycode(["if (!PyInterface_AddNdrRpcMethods(&$interface->{NAME}_InterfaceType, interface_$interface->{NAME}_methods))", "\treturn;", ""]);
        }
 
        $self->pidl_hdr("\n");
@@ -838,6 +794,13 @@ sub register_module_typeobject($$$)
        push (@{$self->{module_types}}, [$name, $py_name])
 }
 
+sub register_module_readycode($$)
+{
+       my ($self, $code) = @_;
+
+       push (@{$self->{readycode}}, @$code);
+}
+
 sub register_module_object($$$)
 {
        my ($self, $name, $py_name) = @_;
@@ -1195,6 +1158,8 @@ sub Parse($$$$$)
                $self->pidl("\treturn;");
        }
 
+       $self->pidl($_) foreach (@{$self->{readycode}});
+
        $self->pidl("");
 
        $self->pidl("m = Py_InitModule3(\"$basename\", $basename\_methods, \"$basename DCE/RPC\");");