From c26aec892f26ee21067a0beb9dd79a8c834e6dba Mon Sep 17 00:00:00 2001 From: Omer Zak Date: Sun, 22 May 2016 11:03:43 +0300 Subject: Added all old files of interest to version control. --- pyscm.c | 577 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 577 insertions(+) create mode 100644 pyscm.c (limited to 'pyscm.c') diff --git a/pyscm.c b/pyscm.c new file mode 100644 index 0000000..1f36fb7 --- /dev/null +++ b/pyscm.c @@ -0,0 +1,577 @@ +// pyscm implementation file +// Python data type for wrapping Guile SCM objects +//////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2008 Omer Zak. +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library, in a file named COPYING; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +// +// For licensing issues, contact . +// +//////////////////////////////////////////////////////////////////////// +// +// Implements PySCM data type - used for wrapping SCM objects in Python +// and making it possible to call them and access/manipulate their +// attributes. + +#include "pyscm.h" +#include "guiletopy.h" +#include "pytoguile.h" +#include "verbose.h" + +//////////////////////////////////////////////////////////////////////// +// Guile Data Structures +//////////////////////////////////////////////////////////////////////// + +static SCM pyscm_registration_hash; // Hash table for preservation of SCMs referred to by PySCM instances. We use *_hashv_* functions for the keys. !!!to ensure that eqv? comparisons are OK here +static long pyscm_registration_index; // Used for building keys for the above hash table. + + +//////////////////////////////////////////////////////////////////////// +// Python Data Structures +//////////////////////////////////////////////////////////////////////// + +//static PyObject *ErrorObject; + +typedef struct { + PyObject_HEAD + long ob_scm_index; // Index into the SCM registration hash table. +} pyscm_PySCMObject; + + +//static struct PyMethodDef pyscm_PySCM_methods[] = { +// {NULL, NULL} /* sentinel */ +//}; + + +static char pyscm_PySCMtype__doc__[] = +"PyGuile SCM wrapper object" +; + + +static int pyscm_PySCM_print(pyscm_PySCMObject *self, FILE *fp, int flags); +static PyObject *pyscm_PySCM_getattr(pyscm_PySCMObject *self, char *name); +static int pyscm_PySCM_setattr(pyscm_PySCMObject *self, + char *name, PyObject *v); +static long pyscm_PySCM_hash(pyscm_PySCMObject *self); +static PyObject *pyscm_PySCM_call(pyscm_PySCMObject *self, + PyObject *args, PyObject *kwargs); +static PyObject *pyscm_PySCM_str(pyscm_PySCMObject *self); +static void pyscm_PySCM_dealloc(pyscm_PySCMObject *self); +static PyObject *pyscm_PySCM_new(PyTypeObject *type, + PyObject *args, PyObject *kwds); + + +static PyTypeObject pyscm_PySCMType = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /*ob_size*/ + "pyscm.PySCM", /*tp_name*/ + sizeof(pyscm_PySCMObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor)pyscm_PySCM_dealloc, /*tp_dealloc*/ + (printfunc)pyscm_PySCM_print, /*tp_print*/ + (getattrfunc)pyscm_PySCM_getattr, /*tp_getattr*/ + (setattrfunc)pyscm_PySCM_setattr, /*tp_setattr*/ + (cmpfunc)0, /*tp_compare*/ + (reprfunc)0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + (hashfunc)pyscm_PySCM_hash, /*tp_hash */ + (ternaryfunc)pyscm_PySCM_call, /*tp_call*/ + (reprfunc)pyscm_PySCM_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/ , /*tp_flags*/ // We don't expect to subclass this class. + pyscm_PySCMtype__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* 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 */ + (initproc)0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)pyscm_PySCM_new, /* tp_new */ +}; + + +//////////////////////////////////////////////////////////////////////// +// Functions +//////////////////////////////////////////////////////////////////////// + +static int +pyscm_PySCM_print(pyscm_PySCMObject *self, FILE *fp, int flags) +{ + PyObject *pstr = pyscm_PySCM_str(self); + if (NULL == pstr) { + scm_memory_error("pyscm_PySCM_print"); + } + int retval = PyObject_Print(pstr,fp,flags); + Py_DECREF(pstr); + return(retval); +} + + +// Documentation of the stemplate data structure, which is paired +// with the actual SCM wrapped by an PySCM instance. +// It is a 5-element vector with the following elements. +// The first 4 elements deal with the SCM being wrapped by a callable +// PySCM. +// If any of the three templates is SCM_EOL, then the corresponding type +// of arguments/result is not expected to exist (if the SCM object +// returns a value to template of SCM_EOL, then the value is discarded +// and None is returned to Python). +// If GET_APPLY_FUNC() has the value SCM_EOL instead of a function, +// it means that the object is not callable. +// +// If the relevant template value is #t, then a default is used. (CANCELLED - when building the template, can use a macro to fill in defaults.) +// 0. p2g template for positional arguments +#define GET_P2G_POSITIONAL_ARGS_TEMPLATE(stemplate) scm_vector_ref(stemplate,scm_long2num(0)) +// 1. p2g template for keyword arguments +#define GET_P2G_KEYWORD_ARGS_TEMPLATE(stemplate) scm_vector_ref(stemplate,scm_long2num(1)) +// 2. g2p template for result +#define GET_G2P_RESULT_TEMPLATE(stemplate) scm_vector_ref(stemplate,scm_long2num(2)) +// 3. function for actually applying the SCM object on the arguments +// (default being 'apply'). +#define GET_APPLY_FUNC(stemplate) scm_vector_ref(stemplate,scm_long2num(3)) +// 4. Either #f or a hash (_hashv_ type) whose keys are described below. +#define GET_ATTRS_HASH(stemplate) scm_vector_ref(stemplate,scm_long2num(4)) +// +// If the 5th element is #f, then the SCM has no attributes. +// Otherwise, the SCM has attributes (which can be either data or methods), +// and the 5th element is supposed to be an hash. +// +// The hash keys are as follows: +// #t - for default values (CANCELLED - when building the template, can use +// a macro to fill in defaults.) +// #f - how to deal with a missing attribute - value can be either +// another #f (throw an attribute error exception to Python) or a +// 4-element vector as described below. +// #:-keyword - refers to attribute 'keyword' +// The values are either #t (to use defaults for everything) (CANCELLED - when +// building the template, can use a macro to fill +// in defaults.) +// or 4-element vectors: +// 0. p2g template for converting __setattr__ value +#define GET_H_P2G_SETATTR_TEMPLATE(shashvalue) scm_vector_ref(shashvalue,scm_long2num(0)) +// 1. g2p template for converting __getattr__ value +#define GET_H_G2P_GETATTR_TEMPLATE(shashvalue) scm_vector_ref(shashvalue,scm_long2num(1)) +// 2. function (func sobj #:-keyword . value) for doing the real +// setattr work; if the value is missing, do delattr. +// It is expected to return #f if it failed, or any other value (including +// SCM_UNDEFINED) if it succeeded. +#define GET_H_SETATTR_FUNC(shashvalue) scm_vector_ref(shashvalue,scm_long2num(2)) +// 3. function (func sobj #:-keyword) for doing the real getattr +// work. +#define GET_H_GETATTR_FUNC(shashvalue) scm_vector_ref(shashvalue,scm_long2num(3)) +// If any of the above is #t then get the corresponding element from +// the default vector. (CANCELLED) +// If any of the GET_H_{GET,SET}ATTR_FUNC values is SCM_EOL, then the +// corresponding function is suppressed. The *_TEMPLATE values must be +// valid whenever the corresponding function exists. +// The value corresponding to the key #f can also be another #f, which +// would cause Python attribute error to be raised. This +// mechanism allows objects to decide how they wish currently-nonexistent +// attributes to be handled. +// In the case of an attribute which is recognized by Python as a method, +// the g2p template for __getattr__ would be a pair of g2p_opaque2PySCM +// and a whole stemplate as described above. +// +// Signatures of SCM functions to be invoked by Python: +// Callable SCM objects wrapped by PySCM - always have two arguments. +// When default templates are used, the first argument's value is a list, +// and the second argument's value is an alist. +// Apply procedure (obtained by GET_APPLY_FUNC()) - has the same signature +// as Scheme's apply procedure i.e. (apply func . args) + + +// Functions for manipulating vectors: +// SCM_VECTORP() +// SCM_VECTOR_LENGTH() +// scm_vector(scm_list_2(sobj1,sobj2)) +// scm_vector_ref(vector,scm_long2num(index_zero_based)) + +// PROBLEM: need to prepend "-" to name before converting it into +// #:-keyword - inefficient! How to eliminate this? + +// Common code for pyscm_PySCM_getattr() and pyscm_PySCM_setattr(): +// Retrieve and return the 4-element vector corresponding to desired +// attribute of the pyscm_PySCMObject. +// Perform also validity checking and raise Python exception if +// invalid. +// Since it is needed later, also the SCM object, corresponding to the +// pyscm_PySCMObject, is returned to the caller, put into 2-element +// list together with the #:-keyword corresponding to name. +static SCM +retrieve_sattr_vector(pyscm_PySCMObject *self, char *name, SCM *sobj_keyword) +{ + SCM shandle = scm_hashv_get_handle(pyscm_registration_hash,scm_long2num(self->ob_scm_index)); + if (SCM_BOOLP(shandle) && SCM_EQ_P(SCM_BOOL_F,shandle)) { + Py_FatalError("PySCM object lost its associated SCM object"); + } + // Now: + // SCM_CADR(shandle) is the SCM object itself + // SCM_CDDR(shandle) is the stemplate. + SCM sattrshash = GET_ATTRS_HASH(SCM_CDDR(shandle)); + + if (SCM_EQ_P(SCM_BOOL_F,sattrshash)) { + PyErr_SetString(PyExc_AttributeError, name); + return(SCM_UNDEFINED); // Error return + } + + // The object has attributes. Build the hash key (a keyword). + + size_t nlength = strlen(name); + char *dashstr = malloc(nlength+2); + dashstr[0] = '-'; + dashstr[1] = '\0'; + strncat(dashstr,name,nlength); + SCM skeyword = scm_make_keyword_from_dash_symbol(scm_str2symbol(dashstr)); + // !!! Do we have to free dashstr? + // !!! Similar code is used also in pytoguile.c - review it. + + SCM sattr_vector_handle = scm_hashv_get_handle(sattrshash,skeyword); + if (SCM_EQ_P(SCM_BOOL_F,sattr_vector_handle)) { + // Missing attribute. How to deal with it? + sattr_vector_handle = scm_hashv_get_handle(sattrshash,SCM_BOOL_F); + if (SCM_EQ_P(SCM_BOOL_F,sattr_vector_handle)) { + // Hash value corresponding to key #f is itself another #f, which + // means that the object does not wish to exhibit to Python + // unknown attributes. + PyErr_SetString(PyExc_AttributeError, name); + return(SCM_UNDEFINED); // Error return + } + // Otherwise, we'll use the hash value corresponding to #f as + // a catch-all for all attributes not otherwise defined. + } + *sobj_keyword = scm_list_2(SCM_CADR(shandle),skeyword); + return(SCM_CDR(sattr_vector_handle)); +} + +static PyObject * +pyscm_PySCM_getattr(pyscm_PySCMObject *self, char *name) +{ + if (pyguile_verbosity_test(PYGUILE_VERBOSE_PYSCM)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# pyscm_PySCM_getattr: trying to get attribute=~S from pobj=~S\n"),scm_list_2(scm_makfrom0str(name),verbosity_repr((PyObject *)self))); + } + SCM sobj_keyword; + SCM sattr_vector = retrieve_sattr_vector(self,name,&sobj_keyword); + if (SCM_UNBNDP(sattr_vector)) { + // Attribute error exception was raised by retrieve_sattr_vector(). + return(NULL); + } + + SCM sgetattr_func = GET_H_GETATTR_FUNC(sattr_vector); + if (SCM_EQ_P(SCM_EOL,sgetattr_func)) { + PyErr_SetString(PyExc_AttributeError, name); + return(NULL); + } + SCM stemplate = GET_H_G2P_GETATTR_TEMPLATE(sattr_vector); + + SCM sresult = scm_apply(sgetattr_func,sobj_keyword,SCM_EOL); + return(g2p_apply(sresult,stemplate)); +} + +static int +pyscm_PySCM_setattr(pyscm_PySCMObject *self, char *name, PyObject *v) +{ + /* Set attribute 'name' to value 'v'. v==NULL means delete */ + if (pyguile_verbosity_test(PYGUILE_VERBOSE_PYSCM)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# pyscm_PySCM_setattr: trying to set attribute=~S from pobj=~S to value ~S\n"),scm_list_3(scm_makfrom0str(name),verbosity_repr((PyObject *)self),verbosity_repr(v))); + } + SCM sobj_keyword; + SCM sattr_vector = retrieve_sattr_vector(self,name,&sobj_keyword); + if (SCM_UNBNDP(sattr_vector)) { + // Attribute error exception was raised by retrieve_sattr_vector(). + return(-1); + } + + SCM ssetattr_func = GET_H_SETATTR_FUNC(sattr_vector); + if (SCM_EQ_P(SCM_EOL,ssetattr_func)) { + PyErr_SetString(PyExc_AttributeError, name); + return(-1); + } + + if (NULL != v) { + SCM sval = p2g_apply(v, + GET_H_P2G_SETATTR_TEMPLATE(sattr_vector)); + scm_append_x(scm_list_2(sobj_keyword,sval)); + } + + SCM sresult = scm_apply(ssetattr_func,sobj_keyword,SCM_EOL); + return(SCM_EQ_P(SCM_BOOL_F,sresult) ? (-1) : 0); +} + +static long +pyscm_PySCM_hash(pyscm_PySCMObject *self) +{ + /* Return a hash of self (or -1) */ + if (pyguile_verbosity_test(PYGUILE_VERBOSE_PYSCM)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# pyscm_PySCM_hash: hash is ~S\n"),scm_list_1(scm_long2num(self->ob_scm_index))); + } + return(self->ob_scm_index); +} + +// Compute logical XOR of a and b +int logical_xor(int a,int b) +{ + return((a == 0) + ? (b != 0) + : (b == 0)); +} +// Compute logical equivalence of a and b (logical inverse of XOR) +int logical_equiv(int a,int b) +{ + return((a != 0) + ? (b != 0) + : (b == 0)); +} + +static PyObject * +pyscm_PySCM_call(pyscm_PySCMObject *self, PyObject *args, PyObject *kwargs) +{ + /* Return the result of calling self with argument args */ + + SCM shandle = scm_hashv_get_handle(pyscm_registration_hash,scm_long2num(self->ob_scm_index)); + if (SCM_BOOLP(shandle) && SCM_EQ_P(SCM_BOOL_F,shandle)) { + Py_FatalError("PySCM object lost its associated SCM object"); // NOT COVERED BY TESTS + } + // Now: + // SCM_CADR(shandle) is the SCM object itself + // SCM_CDDR(shandle) is the stemplate. + if (pyguile_verbosity_test(PYGUILE_VERBOSE_PYSCM)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# pyscm_PySCM_call: calling ~S with args=~S and keywords=~S; stemplate=~S\n"),scm_list_4(SCM_CADR(shandle),verbosity_repr(args),verbosity_repr(kwargs),SCM_CDDR(shandle))); + } + + SCM sapply_func = GET_APPLY_FUNC(SCM_CDDR(shandle)); + if (SCM_EQ_P(SCM_EOL,sapply_func)) { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_PYSCM)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# pyscm_PySCM_call: raising exceptions.TypeError due to \"PySCM wraps a non-callable SCM\"\n"),SCM_EOL); + } + PyErr_SetString(PyExc_TypeError, "PySCM wraps a non-callable SCM"); + return(NULL); + } + + // Process arguments. + SCM sargs_template = GET_P2G_POSITIONAL_ARGS_TEMPLATE(SCM_CDDR(shandle)); + SCM skwargs_template = GET_P2G_KEYWORD_ARGS_TEMPLATE(SCM_CDDR(shandle)); + /*if (logical_xor(SCM_EQ_P(SCM_EOL,sargs_template),(NULL==args)) + || logical_xor(SCM_EQ_P(SCM_EOL,skwargs_template),(NULL==kwargs)))*/ + // The following allows template to exist without actual arguments. + if ((SCM_EQ_P(SCM_EOL,sargs_template) && (NULL != args)) + || (SCM_EQ_P(SCM_EOL,skwargs_template) && (NULL != kwargs))) { + if (pyguile_verbosity_test(PYGUILE_VERBOSE_PYSCM)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# pyscm_PySCM_call: raising exceptions.TypeError due to \"wrapped SCM does not take some of the provided arguments\"\n"),SCM_EOL); + } + PyErr_SetString(PyExc_TypeError, "wrapped SCM does not take some of the provided arguments"); + return(NULL); + } + + SCM sargs = SCM_EQ_P(SCM_EOL,sargs_template) || (NULL == args) + ? SCM_EOL : p2g_apply(args,sargs_template); + SCM skwargs = SCM_EQ_P(SCM_EOL,skwargs_template) || (NULL == kwargs) + ? SCM_EOL : p2g_apply(kwargs,skwargs_template); + + SCM sresult = scm_apply(sapply_func,scm_list_2(SCM_CADR(shandle),scm_list_2(sargs,skwargs)),SCM_EOL); + SCM sresult_template = GET_G2P_RESULT_TEMPLATE(SCM_CDDR(shandle)); + if (SCM_EQ_P(SCM_EOL,sresult_template)) { + Py_RETURN_NONE; + } + else { + return(g2p_apply(sresult,sresult_template)); + } +} + +// Does not include the template object in the string representation. +static PyObject * +pyscm_PySCM_str(pyscm_PySCMObject *self) +{ + if (0 == self->ob_scm_index) { + return(PyString_FromString("")); + } + SCM shandle = scm_hashv_get_handle(pyscm_registration_hash,scm_long2num(self->ob_scm_index)); + if (SCM_BOOLP(shandle) && SCM_EQ_P(SCM_BOOL_F,shandle)) { + Py_FatalError("PySCM object lost its associated SCM object"); + } + SCM sstr = scm_object_to_string(SCM_CADR(shandle),scm_variable_ref(scm_c_lookup("write"))); + + PyObject *pstr = PyString_FromStringAndSize(SCM_STRING_CHARS(sstr),SCM_STRING_LENGTH(sstr)); + return(pstr); // possibly NULL. +} + +static void +pyscm_PySCM_dealloc(pyscm_PySCMObject *self) +{ + if (pyguile_verbosity_test(PYGUILE_VERBOSE_GC_PYSCM)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# pyscm_PySCM_dealloc: deallocating PySCMObject with hash ~S\n"),scm_list_1(scm_long2num(self->ob_scm_index))); + } + if (0 != self->ob_scm_index) { + // Unregister the associated SCM from the hash table. + SCM shashkey = scm_long2num(self->ob_scm_index); + scm_hashv_remove_x(pyscm_registration_hash,shashkey); + // If ob_scm_index is zero, no SCM was associated yet with + // this PySCM instance. + } + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject * +pyscm_PySCM_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + pyscm_PySCMObject *self; + if (pyguile_verbosity_test(PYGUILE_VERBOSE_GC_PYSCM)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# pyscm_PySCM_new: was called\n"),SCM_EOL); + } + self = (pyscm_PySCMObject *)type->tp_alloc(type,0); + if (NULL != self) { + self->ob_scm_index = 0; + } + return((PyObject *)self); +} + +//////////////////////////////////////////////////////////////////////// +// Interface to the rest of PyGuile +//////////////////////////////////////////////////////////////////////// + +// Create a pyscm_PySCMObject instance, which wraps sobj and associates +// with it with template for data conversions when python accesses data +// and functions/methods associated with sobj. +PyObject * +wrap_scm(SCM sobj,SCM stemplate) +{ + if (pyguile_verbosity_test(PYGUILE_VERBOSE_PYSCM)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# wrap_scm: was called to wrap ~S\n"),scm_list_1(sobj)); + } + pyscm_PySCMObject *pwrapper = PyObject_New(pyscm_PySCMObject,&pyscm_PySCMType); + if (NULL == pwrapper) { + scm_memory_error("wrap_scm"); // NOT COVERED BY TESTS + } + //PyObject_Init(pwrapper,&pyscm_PySCMType); // Is it needed or does PyObject_New() take care of it? + //if (NULL == pwrapper) { + // scm_misc_error("wrap_scm","could not wrap object ~S with PySCM when using conversion template ~S", + // scm_list_2(sobj,stemplate)); + //} + else { + SCM sconsed = scm_cons(sobj,stemplate); + SCM shashkey = scm_long2num(++pyscm_registration_index); + scm_hashv_create_handle_x(pyscm_registration_hash,shashkey,sconsed); + pwrapper->ob_scm_index = pyscm_registration_index; + return((PyObject *)pwrapper); + } +} + +// Return 0 if pobj is not of this type and/or does not wrap a SCM. +// Otherwise, return a nonzero value. +int +PySCMObject_Check(PyObject *pobj) +{ + if (!PyObject_TypeCheck(pobj, &pyscm_PySCMType)) { + return(0); + } + return ((0 == ((pyscm_PySCMObject *)pobj)->ob_scm_index) + ? 0 // pobj does not actually wrap a SCM. + : 1); +} + +// Unwrap a pyscm_PySCMObject instance and get from it the original +// SCM object. If the object is not a pyscm_PySCMObject or does not +// wrap a SCM object, raise an error. +SCM +unwrap_pyscm_object(PyObject *pobj) +{ + if (pyguile_verbosity_test(PYGUILE_VERBOSE_PYSCM)) { + scm_simple_format(scm_current_output_port(),scm_makfrom0str("# unwrap_pyscm_object: trying to unwrap pobj=~S\n"),scm_list_1(verbosity_repr(pobj))); + } + + if (!PySCMObject_Check(pobj)) { + Py_FatalError("Trying to pyscm-unwrap a non-PySCM"); + } + SCM shandle = scm_hashv_get_handle(pyscm_registration_hash,scm_long2num(((pyscm_PySCMObject *)pobj)->ob_scm_index)); + return(SCM_CADR(shandle)); +} + +//////////////////////////////////////////////////////////////////////// +// Initializer +//////////////////////////////////////////////////////////////////////// + +static struct PyMethodDef pyscm_methods[] = { + + {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */ +}; + + +/* Initialization function for the module (*must* be called initpyscm) */ + +static char pyscm_module_documentation[] = +"pyscm - defines the Custom Python datatype PySCM for wrapping SCM objects" +; + +#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ +#define PyMODINIT_FUNC void +#endif +PyMODINIT_FUNC +initpyscm(void) +{ + PyObject *m; + + /*pyscm_PySCMType.tp_new = PyType_GenericNew;*/ + if (PyType_Ready(&pyscm_PySCMType) < 0) { + return; // NOT COVERED BY TESTS + } + + /* Create the module and add the functions */ + m = Py_InitModule4("pyscm", pyscm_methods, + pyscm_module_documentation, + (PyObject*)NULL,PYTHON_API_VERSION); + if (NULL == m) { + return; // NOT COVERED BY TESTS + } + + Py_INCREF(&pyscm_PySCMType); + PyModule_AddObject(m, "PySCM", (PyObject *)&pyscm_PySCMType); + + /* Add some symbolic constants to the module */ + //PyObject *d; + //d = PyModule_GetDict(m); + //ErrorObject = PyString_FromString("pyscm.error"); + //PyDict_SetItemString(d, "error", ErrorObject); + + /* Add constants here */ + // Currently, none is needed. + + /* Check for errors */ + if (PyErr_Occurred()) { + Py_FatalError("can't initialize module pyscm"); // NOT COVERED BY TESTS + } + + // This part initializes the Guile data structures needed + // by this module. + pyscm_registration_hash = scm_permanent_object(scm_c_make_hash_table(65537)); + pyscm_registration_index = 0; +} + +//////////////////////////////////////////////////////////////////////// +// End of pyscm.c -- cgit v1.2.3