summaryrefslogtreecommitdiff
path: root/pidl
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2016-09-12 16:33:38 +0200
committerAndreas Schneider <asn@cryptomilk.org>2016-10-26 11:20:19 +0200
commite0324c0cf7e7c363a5791c2e35c8820b79640a47 (patch)
tree587303e26c6c788bf9ae1f744ce85982bac13849 /pidl
parent596f917693315cddcf4c453e75410ef786a7a8b0 (diff)
downloadsamba-e0324c0cf7e7c363a5791c2e35c8820b79640a47.tar.gz
pidl:Python: provide a PyTypeObject with METH_CLASS __import__() and __export__() hooks
These are wrappers around the currently public C functions 'py_import_*() and 'py_export_*(). In order to let other python module use these function, we should resolve the needed type object and call the __import__() or __export__() hooks instead of linking to the other shared module at C level. We already do the same for structs. Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
Diffstat (limited to 'pidl')
-rw-r--r--pidl/lib/Parse/Pidl/Samba4/Python.pm214
1 files changed, 214 insertions, 0 deletions
diff --git a/pidl/lib/Parse/Pidl/Samba4/Python.pm b/pidl/lib/Parse/Pidl/Samba4/Python.pm
index fe7b2a01cd8..4c24500b02a 100644
--- a/pidl/lib/Parse/Pidl/Samba4/Python.pm
+++ b/pidl/lib/Parse/Pidl/Samba4/Python.pm
@@ -671,6 +671,11 @@ sub PythonType($$$$)
}
if ($actual_ctype->{TYPE} eq "UNION" and defined($actual_ctype->{ELEMENTS})) {
+ my $prettyname = PrettifyTypeName($d->{NAME}, $basename);
+ my $typeobject = "$d->{NAME}\_Type";
+ my $docstring = $self->DocString($d, $d->{NAME});
+ my $cname = "union $d->{NAME}";
+
$self->pidl("PyObject *py_import_$d->{NAME}(TALLOC_CTX *mem_ctx, int level, " .mapTypeName($d) . " *in)");
$self->pidl_hdr("PyObject *py_import_$d->{NAME}(TALLOC_CTX *mem_ctx, int level, " .mapTypeName($d) . " *in);\n");
$self->pidl("{");
@@ -688,6 +693,215 @@ sub PythonType($$$$)
$self->deindent;
$self->pidl("}");
$self->pidl("");
+
+ my $getsetters = "NULL";
+ my $py_methods = "NULL";
+ my $typename = mapTypeName($d);
+
+ ##
+ ## PyCapsule (starting with 2.7) vs. PyCObject (up to 3.2)
+ ##
+ ## As we need to support python 2.6, we can't use PyCapsule yet.
+ ##
+ ## When we'll get support fpr Python3 we'll have to emulate
+ ## PyCObject using PyCapsule and convert these functions to
+ ## use PyCapsule.
+ ##
+ $self->pidl("static PyObject *py_$d->{NAME}\_import(PyTypeObject *type, PyObject *args, PyObject *kwargs)");
+ $self->pidl("{");
+ $self->indent;
+ $self->pidl("const char * const kwnames[] = { \"mem_ctx\", \"level\", \"in\", NULL };");
+ $self->pidl("PyObject *mem_ctx_obj = NULL;");
+ $self->pidl("static const char *mem_ctx_type = \"TALLOC_CTX\";");
+ $self->pidl("const char *mem_ctx_desc = NULL;");
+ $self->pidl("TALLOC_CTX *mem_ctx = NULL;");
+ $self->pidl("int level = 0;");
+ $self->pidl("PyObject *in_obj = NULL;");
+ $self->pidl("static const char *in_type = \"$typename\";");
+ $self->pidl("const char *in_desc = NULL;");
+ $self->pidl("$typename *in = NULL;");
+ $self->pidl("int cmp;");
+ $self->pidl("");
+ $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"OiO:import\",");
+ $self->indent;
+ $self->pidl("discard_const_p(char *, kwnames),");
+ $self->pidl("&mem_ctx_obj,");
+ $self->pidl("&level,");
+ $self->pidl("&in_obj)) {");
+ $self->deindent;
+ $self->indent;
+ $self->pidl("return NULL;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("if (!PyCObject_Check(mem_ctx_obj)) {");
+ $self->indent;
+ $self->pidl("PyErr_SetString(PyExc_TypeError, \"mem_ctx needs to be of type PyCObject!\");");
+ $self->pidl("return NULL;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("mem_ctx_desc = (const char *)PyCObject_GetDesc(mem_ctx_obj);");
+ $self->indent;
+ $self->pidl("if (mem_ctx_desc == NULL) {");
+ $self->pidl("PyErr_SetString(PyExc_TypeError, \"mem_ctx hash no PyCObject_GetDesc()!\");");
+ $self->pidl("return NULL;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("cmp = strncmp(mem_ctx_type, mem_ctx_desc, strlen(mem_ctx_type) + 1);");
+ $self->pidl("if (cmp != 0) {");
+ $self->indent;
+ $self->pidl("PyErr_Format(PyExc_TypeError, \"mem_ctx should have PyCObject_GetDesc() = %s!\", mem_ctx_type);");
+ $self->pidl("return NULL;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("mem_ctx = PyCObject_AsVoidPtr(mem_ctx_obj);");
+ $self->pidl("if (mem_ctx == NULL) {");
+ $self->indent;
+ $self->pidl("PyErr_SetString(PyExc_TypeError, \"mem_ctx is NULL)!\");");
+ $self->pidl("return NULL;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("if (!PyCObject_Check(in_obj)) {");
+ $self->indent;
+ $self->pidl("PyErr_SetString(PyExc_TypeError, \"in needs to be of type PyCObject!\");");
+ $self->pidl("return NULL;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("in_desc = (const char *)PyCObject_GetDesc(in_obj);");
+ $self->indent;
+ $self->pidl("if (in_desc == NULL) {");
+ $self->pidl("PyErr_SetString(PyExc_TypeError, \"in hash no PyCObject_GetDesc()!\");");
+ $self->pidl("return NULL;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("cmp = strncmp(in_type, in_desc, strlen(in_type) + 1);");
+ $self->pidl("if (cmp != 0) {");
+ $self->indent;
+ $self->pidl("PyErr_Format(PyExc_TypeError, \"in should have PyCObject_GetDesc() = %s!\", in_type);");
+ $self->pidl("return NULL;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("in = ($typename *)PyCObject_AsVoidPtr(in_obj);");
+ $self->pidl("");
+ $self->pidl("return py_import_$d->{NAME}(mem_ctx, level, in);");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("");
+
+ $self->pidl("static PyObject *py_$d->{NAME}\_export(PyTypeObject *type, PyObject *args, PyObject *kwargs)");
+ $self->pidl("{");
+ $self->indent;
+ $self->pidl("const char * const kwnames[] = { \"mem_ctx\", \"level\", \"in\", NULL };");
+ $self->pidl("PyObject *mem_ctx_obj = NULL;");
+ $self->pidl("static const char *mem_ctx_type = \"TALLOC_CTX\";");
+ $self->pidl("const char *mem_ctx_desc = NULL;");
+ $self->pidl("TALLOC_CTX *mem_ctx = NULL;");
+ $self->pidl("int level = 0;");
+ $self->pidl("PyObject *in = NULL;");
+ $self->pidl("static const char *out_type = \"$typename\";");
+ $self->pidl("$typename *out = NULL;");
+ $self->pidl("int cmp;");
+ $self->pidl("");
+ $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"OiO:import\",");
+ $self->indent;
+ $self->pidl("discard_const_p(char *, kwnames),");
+ $self->pidl("&mem_ctx_obj,");
+ $self->pidl("&level,");
+ $self->pidl("&in)) {");
+ $self->deindent;
+ $self->indent;
+ $self->pidl("return NULL;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("if (!PyCObject_Check(mem_ctx_obj)) {");
+ $self->indent;
+ $self->pidl("PyErr_SetString(PyExc_TypeError, \"mem_ctx needs to be of type PyCObject!\");");
+ $self->pidl("return NULL;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("mem_ctx_desc = (const char *)PyCObject_GetDesc(mem_ctx_obj);");
+ $self->indent;
+ $self->pidl("if (mem_ctx_desc == NULL) {");
+ $self->pidl("PyErr_SetString(PyExc_TypeError, \"mem_ctx hash no PyCObject_GetDesc()!\");");
+ $self->pidl("return NULL;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("cmp = strncmp(mem_ctx_type, mem_ctx_desc, strlen(mem_ctx_type) + 1);");
+ $self->pidl("if (cmp != 0) {");
+ $self->indent;
+ $self->pidl("PyErr_Format(PyExc_TypeError, \"mem_ctx should have PyCObject_GetDesc() = %s!\", mem_ctx_type);");
+ $self->pidl("return NULL;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("mem_ctx = PyCObject_AsVoidPtr(mem_ctx_obj);");
+ $self->pidl("if (mem_ctx == NULL) {");
+ $self->indent;
+ $self->pidl("PyErr_SetString(PyExc_TypeError, \"mem_ctx is NULL)!\");");
+ $self->pidl("return NULL;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("");
+ $self->pidl("out = py_export_$d->{NAME}(mem_ctx, level, in);");
+ $self->pidl("if (out == NULL) {");
+ $self->indent;
+ $self->pidl("return NULL;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("return PyCObject_FromVoidPtrAndDesc(out, discard_const_p(char, out_type), NULL);");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("");
+
+ $py_methods = "py_$d->{NAME}_methods";
+ $self->pidl("static PyMethodDef $py_methods\[] = {");
+ $self->indent;
+ $self->pidl("{ \"__import__\", (PyCFunction)py_$d->{NAME}\_import,");
+ $self->indent;
+ $self->pidl("METH_VARARGS|METH_KEYWORDS|METH_CLASS,");
+ $self->pidl("\"T.__import__(mem_ctx, level, in) => ret.\" },");
+ $self->deindent;
+ $self->pidl("{ \"__export__\", (PyCFunction)py_$d->{NAME}\_export,");
+ $self->indent;
+ $self->pidl("METH_VARARGS|METH_KEYWORDS|METH_CLASS,");
+ $self->pidl("\"T.__export__(mem_ctx, level, in) => ret.\" },");
+ $self->deindent;
+ $self->pidl("{ NULL, NULL, 0, NULL }");
+ $self->deindent;
+ $self->pidl("};");
+ $self->pidl("");
+
+ $self->pidl("static PyObject *py_$d->{NAME}\_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)");
+ $self->pidl("{");
+ $self->indent;
+ $self->pidl("PyErr_Format(PyExc_TypeError, \"New %s Objects are not supported\", type->tp_name);");
+ $self->pidl("return NULL;");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("");
+
+ $self->pidl("");
+ $self->pidl_hdr("static PyTypeObject $typeobject;\n");
+ $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_$d->{NAME}\_new,");
+ $self->deindent;
+ $self->pidl("};");
+
+ $self->pidl("");
+
+ my $talloc_typename = $self->import_type_variable("talloc", "BaseObject");
+ $self->register_module_prereadycode(["$typeobject.tp_base = $talloc_typename;",
+ "$typeobject.tp_basicsize = pytalloc_BaseObject_size();",
+ ""]);
+
+ $self->register_module_typeobject($prettyname, "&$typeobject", $d->{ORIGINAL});
}
}