Add CFCPython. Start with writing cfish_hostdefs.h.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/b10130e0 Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/b10130e0 Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/b10130e0 Branch: refs/heads/master Commit: b10130e067253b05cb57c213157d6e901805eebe Parents: 1cf2a6d Author: Marvin Humphrey <[email protected]> Authored: Thu Dec 18 18:43:29 2014 -0800 Committer: Marvin Humphrey <[email protected]> Committed: Sat Feb 6 09:58:13 2016 -0800 ---------------------------------------------------------------------- compiler/include/CFC.h | 2 + compiler/python/src/cfc/_cfc.c | 125 ++++++++++++++++++++++++++++++++++-- compiler/src/CFCPython.c | 115 +++++++++++++++++++++++++++++++++ compiler/src/CFCPython.h | 63 ++++++++++++++++++ 4 files changed, 300 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b10130e0/compiler/include/CFC.h ---------------------------------------------------------------------- diff --git a/compiler/include/CFC.h b/compiler/include/CFC.h index 9d1c222..1bdc968 100644 --- a/compiler/include/CFC.h +++ b/compiler/include/CFC.h @@ -57,5 +57,7 @@ #include "CFCPerlPod.h" #include "CFCPerlTypeMap.h" +#include "CFCPython.h" + #include "CFCRuby.h" http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b10130e0/compiler/python/src/cfc/_cfc.c ---------------------------------------------------------------------- diff --git a/compiler/python/src/cfc/_cfc.c b/compiler/python/src/cfc/_cfc.c index d20b5fa..24e45a4 100644 --- a/compiler/python/src/cfc/_cfc.c +++ b/compiler/python/src/cfc/_cfc.c @@ -103,9 +103,16 @@ S_to_BindCore(PyObject *wrapper) { "Clownfish::CFC::Binding::Core"); } +static CFCPython* +S_to_BindPython(PyObject *wrapper) { + return (CFCPython*)S_to_cfc_something(wrapper, + "Clownfish::CFC::Binding::Python"); +} + static PyTypeObject *Hierarchy_pytype; static PyTypeObject *Parcel_pytype; static PyTypeObject *BindCore_pytype; +static PyTypeObject *BindPython_pytype; /***************************** CFCHierarchy *****************************/ @@ -173,6 +180,13 @@ S_CFCHierarchy_add_source_dir(PyObject *wrapper, PyObject *dir) { } static PyObject* +S_CFCHierarchy_get_dest(PyObject *wrapper, PyObject *unused) { + CHY_UNUSED_VAR(unused); + const char *dest = CFCHierarchy_get_dest(S_to_Hierarchy(wrapper)); + return PyUnicode_DecodeASCII(dest, strlen(dest), NULL); +} + +static PyObject* S_CFCHierarchy_write_log(PyObject *wrapper, PyObject *unused) { CHY_UNUSED_VAR(unused); CFCHierarchy_write_log(S_to_Hierarchy(wrapper)); @@ -183,6 +197,7 @@ static PyMethodDef hierarchy_methods[] = { {"add_include_dir", (PyCFunction)S_CFCHierarchy_add_include_dir, METH_O, NULL}, {"add_source_dir", (PyCFunction)S_CFCHierarchy_add_source_dir, METH_O, NULL}, {"build", (PyCFunction)S_CFCHierarchy_build, METH_NOARGS, NULL}, + {"get_dest", (PyCFunction)S_CFCHierarchy_get_dest, METH_NOARGS, NULL}, {"write_log", (PyCFunction)S_CFCHierarchy_write_log, METH_NOARGS, NULL}, {NULL} }; @@ -306,8 +321,13 @@ S_CFCBindCore_write_all_modified(PyObject *wrapper, PyObject *args) { int modified = 0; int result = PyArg_ParseTuple(args, "|p", &modified); if (!result) { return NULL; } - CFCBindCore_write_all_modified(S_to_BindCore(wrapper), modified); - Py_RETURN_NONE; + modified = CFCBindCore_write_all_modified(S_to_BindCore(wrapper), modified); + if (modified) { + Py_RETURN_TRUE; + } + else { + Py_RETURN_FALSE; + } } static PyMethodDef bindcore_methods[] = { @@ -356,14 +376,103 @@ static PyTypeObject BindCore_pytype_struct = { (newfunc)S_CFCBindCore_new // tp_new }; +/***************************** CFCPython *****************************/ + +static PyObject* +S_CFCPython_new(PyTypeObject *type, PyObject *args, PyObject *keyword_args) { + PyObject *hierarchy_wrapped; + char *keywords[] = {"hierarchy", NULL}; + int result = PyArg_ParseTupleAndKeywords(args, keyword_args, "O!", + keywords, Hierarchy_pytype, + &hierarchy_wrapped); + if (!result) { return NULL; } + CFCHierarchy *hierarchy = S_to_Hierarchy(hierarchy_wrapped); + CFCPython *obj = CFCPython_new(hierarchy); + return S_wrap_cfcbase(BindPython_pytype, obj); +} + +static PyObject* +S_CFCPython_set_header(PyObject *wrapper, PyObject *header) { + CFCPython_set_header(S_to_BindPython(wrapper), PyUnicode_AsUTF8(header)); + Py_RETURN_NONE; +} + +static PyObject* +S_CFCPython_set_footer(PyObject *wrapper, PyObject *footer) { + CFCPython_set_footer(S_to_BindPython(wrapper), PyUnicode_AsUTF8(footer)); + Py_RETURN_NONE; +} + +static PyObject* +S_CFCPython_write_bindings(PyObject *wrapper, PyObject *args, + PyObject *keyword_args) { + char *parcel; + char *dest; + char *keywords[] = {"parcel", "dest", NULL}; + int result = PyArg_ParseTupleAndKeywords(args, keyword_args, "ss", + keywords, &parcel, &dest); + if (!result) { return NULL; } + CFCPython_write_bindings(S_to_BindPython(wrapper), parcel, dest); + Py_RETURN_NONE; +} + +static PyMethodDef bindpython_methods[] = { + {"set_header", (PyCFunction)S_CFCPython_set_header, METH_O, NULL}, + {"set_footer", (PyCFunction)S_CFCPython_set_footer, METH_O, NULL}, + {"write_bindings", (PyCFunction)S_CFCPython_write_bindings, METH_KEYWORDS|METH_VARARGS, NULL}, + {NULL} +}; + +static PyTypeObject BindPython_pytype_struct = { + PyVarObject_HEAD_INIT(NULL, 0) + "cfc.binding.Python", // tp_name + sizeof(CFCPyWrapper), // tp_basicsize + 0, // tp_itemsize + (destructor)S_CFCBase_dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_reserved + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "CFCBindPython", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + bindpython_methods, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + 0, // tp_allow + (newfunc)S_CFCPython_new // tp_new +}; + /******************************* common ******************************/ PyMODINIT_FUNC PyInit__cfc(void) { // Initialize Python type objects. - Hierarchy_pytype = &Hierarchy_pytype_struct; - Parcel_pytype = &Parcel_pytype_struct; - BindCore_pytype = &BindCore_pytype_struct; + Hierarchy_pytype = &Hierarchy_pytype_struct; + Parcel_pytype = &Parcel_pytype_struct; + BindCore_pytype = &BindCore_pytype_struct; + BindPython_pytype = &BindPython_pytype_struct; if (PyType_Ready(Hierarchy_pytype) < 0) { return NULL; } @@ -373,6 +482,9 @@ PyInit__cfc(void) { if (PyType_Ready(BindCore_pytype) < 0) { return NULL; } + if (PyType_Ready(BindPython_pytype) < 0) { + return NULL; + } // Initialize modules. cfc_module = PyModule_Create(&cfc_module_def); @@ -393,6 +505,9 @@ PyInit__cfc(void) { Py_INCREF(BindCore_pytype); PyModule_AddObject(cfc_binding_module, "BindCore", (PyObject*)BindCore_pytype); + Py_INCREF(BindCore_pytype); + PyModule_AddObject(cfc_binding_module, "Python", + (PyObject*)BindPython_pytype); return cfc_module; } http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b10130e0/compiler/src/CFCPython.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c new file mode 100644 index 0000000..729570a --- /dev/null +++ b/compiler/src/CFCPython.c @@ -0,0 +1,115 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "charmony.h" + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +#define CFC_NEED_BASE_STRUCT_DEF +#include "CFCBase.h" +#include "CFCPython.h" +#include "CFCParcel.h" +#include "CFCClass.h" +#include "CFCMethod.h" +#include "CFCHierarchy.h" +#include "CFCUtil.h" +#include "CFCBindCore.h" + +struct CFCPython { + CFCBase base; + CFCHierarchy *hierarchy; + char *header; + char *footer; +}; + +void +S_destroy(CFCPython *self); + +static const CFCMeta CFCPYTHON_META = { + "Clownfish::CFC::Binding::Python", + sizeof(CFCPython), + (CFCBase_destroy_t)S_destroy +}; + +CFCPython* +CFCPython_new(CFCHierarchy *hierarchy) { + CFCUTIL_NULL_CHECK(hierarchy); + CFCPython *self = (CFCPython*)CFCBase_allocate(&CFCPYTHON_META); + self->hierarchy = (CFCHierarchy*)CFCBase_incref((CFCBase*)hierarchy); + self->header = CFCUtil_strdup(""); + self->footer = CFCUtil_strdup(""); + return self; +} + +void +S_destroy(CFCPython *self) { + CFCBase_decref((CFCBase*)self->hierarchy); + FREEMEM(self->header); + FREEMEM(self->footer); + CFCBase_destroy((CFCBase*)self); +} + +void +CFCPython_set_header(CFCPython *self, const char *header) { + CFCUTIL_NULL_CHECK(header); + free(self->header); + self->header = CFCUtil_make_c_comment(header); +} + +void +CFCPython_set_footer(CFCPython *self, const char *footer) { + CFCUTIL_NULL_CHECK(footer); + free(self->footer); + self->footer = CFCUtil_make_c_comment(footer); +} + +static void +S_write_hostdefs(CFCPython *self) { + const char pattern[] = + "%s\n" + "\n" + "#ifndef H_CFISH_HOSTDEFS\n" + "#define H_CFISH_HOSTDEFS 1\n" + "\n" + "#include \"Python.h\"\n" + "\n" + "#define CFISH_OBJ_HEAD \\\n" + " PyObject_HEAD\n" + "\n" + "#endif /* H_CFISH_HOSTDEFS */\n" + "\n" + "%s\n"; + char *content + = CFCUtil_sprintf(pattern, self->header, self->footer); + + // Write if the content has changed. + const char *inc_dest = CFCHierarchy_get_include_dest(self->hierarchy); + char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "cfish_hostdefs.h", + inc_dest); + CFCUtil_write_if_changed(filepath, content, strlen(content)); + + FREEMEM(filepath); + FREEMEM(content); +} + +void +CFCPython_write_bindings(CFCPython *self, const char *parcel_name, const char *dest) { + S_write_hostdefs(self); +} + http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b10130e0/compiler/src/CFCPython.h ---------------------------------------------------------------------- diff --git a/compiler/src/CFCPython.h b/compiler/src/CFCPython.h new file mode 100644 index 0000000..6fa846a --- /dev/null +++ b/compiler/src/CFCPython.h @@ -0,0 +1,63 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H_CFCPYTHON +#define H_CFCPYTHON + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct CFCPython CFCPython; +struct CFCParcel; +struct CFCHierarchy; + +/** Clownfish::CFC::Binding::Python - Python bindings for a + * Clownfish::CFC::Model::Hierarchy. + * + * Clownfish::CFC::Binding::Python presents an interface for auto-generating + * Python C API code to bind to a Clownfish class hierarchy. + */ + +/** + * @param hierarchy A CFCHierarchy. + */ + +CFCPython* +CFCPython_new(struct CFCHierarchy *hierarchy); + +/** Set the text which will be prepended to generated C files -- for + * instance, an "autogenerated file" warning. + */ +void +CFCPython_set_header(CFCPython *self, const char *header); + +/** Set the text which will be appended to the end of generated C files. + */ +void +CFCPython_set_footer(CFCPython *self, const char *footer); + +/** Generate Python bindings for the specified parcel. + */ +void +CFCPython_write_bindings(CFCPython *self, const char *parcel, const char *dest); + +#ifdef __cplusplus +} +#endif + +#endif /* H_CFCPYTHON */ +
