summaryrefslogtreecommitdiff
path: root/scipy/weave/c_spec.py
diff options
context:
space:
mode:
authorTravis Oliphant <oliphant@enthought.com>2006-01-02 08:26:24 +0000
committerTravis Oliphant <oliphant@enthought.com>2006-01-02 08:26:24 +0000
commit4712a37b93832933a46376ee99339f9040ba3670 (patch)
tree8a3de8500925061b0f2368fae2d50159dbea206f /scipy/weave/c_spec.py
parentb5ba0003def4cfa43b29d29df8f085d09609707b (diff)
downloadnumpy-4712a37b93832933a46376ee99339f9040ba3670.tar.gz
Moved weave to scipy
Diffstat (limited to 'scipy/weave/c_spec.py')
-rw-r--r--scipy/weave/c_spec.py468
1 files changed, 0 insertions, 468 deletions
diff --git a/scipy/weave/c_spec.py b/scipy/weave/c_spec.py
deleted file mode 100644
index b848eb97d..000000000
--- a/scipy/weave/c_spec.py
+++ /dev/null
@@ -1,468 +0,0 @@
-from types import *
-from base_spec import base_converter
-import base_info
-
-#----------------------------------------------------------------------------
-# C++ code template for converting code from python objects to C++ objects
-#
-# This is silly code. There is absolutely no reason why these simple
-# conversion functions should be classes. However, some versions of
-# Mandrake Linux ship with broken C++ compilers (or libraries) that do not
-# handle exceptions correctly when they are thrown from functions. However,
-# exceptions thrown from class methods always work, so we make everything
-# a class method to solve this error.
-#----------------------------------------------------------------------------
-
-#----------------------------------------------------------------------------
-# speed note
-# the convert_to_int macro below takes about 25 ns per conversion on my
-# 850 MHz PIII. A slightly more sophisticated macro version can trim this
-# to 20 ns, but this savings is dang near useless because the other
-# overhead swamps it...
-#----------------------------------------------------------------------------
-py_to_c_template = \
-"""
-class %(type_name)s_handler
-{
-public:
- %(return_type)s convert_to_%(type_name)s(PyObject* py_obj, const char* name)
- {
- // Incref occurs even if conversion fails so that
- // the decref in cleanup_code has a matching incref.
- %(inc_ref_count)s
- if (!py_obj || !%(check_func)s(py_obj))
- handle_conversion_error(py_obj,"%(type_name)s", name);
- return %(to_c_return)s;
- }
-
- %(return_type)s py_to_%(type_name)s(PyObject* py_obj, const char* name)
- {
- // !! Pretty sure INCREF should only be called on success since
- // !! py_to_xxx is used by the user -- not the code generator.
- if (!py_obj || !%(check_func)s(py_obj))
- handle_bad_type(py_obj,"%(type_name)s", name);
- %(inc_ref_count)s
- return %(to_c_return)s;
- }
-};
-
-%(type_name)s_handler x__%(type_name)s_handler = %(type_name)s_handler();
-#define convert_to_%(type_name)s(py_obj,name) \\
- x__%(type_name)s_handler.convert_to_%(type_name)s(py_obj,name)
-#define py_to_%(type_name)s(py_obj,name) \\
- x__%(type_name)s_handler.py_to_%(type_name)s(py_obj,name)
-
-"""
-
-#----------------------------------------------------------------------------
-# C++ code template for converting code from C++ objects to Python objects
-#
-#----------------------------------------------------------------------------
-
-simple_c_to_py_template = \
-"""
-PyObject* %(type_name)s_to_py(PyObject* obj)
-{
- return (PyObject*) obj;
-}
-
-"""
-
-class common_base_converter(base_converter):
-
- def __init__(self):
- self.init_info()
- self._build_information = [self.generate_build_info()]
-
- def init_info(self):
- self.matching_types = []
- self.headers = []
- self.include_dirs = []
- self.libraries = []
- self.library_dirs = []
- self.sources = []
- self.support_code = []
- self.module_init_code = []
- self.warnings = []
- self.define_macros = []
- self.extra_compile_args = []
- self.extra_link_args = []
- self.use_ref_count = 1
- self.name = "no_name"
- self.c_type = 'PyObject*'
- self.return_type = 'PyObject*'
- self.to_c_return = 'py_obj'
-
- def info_object(self):
- return base_info.custom_info()
-
- def generate_build_info(self):
- info = self.info_object()
- for header in self.headers:
- info.add_header(header)
- for d in self.include_dirs:
- info.add_include_dir(d)
- for lib in self.libraries:
- info.add_library(lib)
- for d in self.library_dirs:
- info.add_library_dir(d)
- for source in self.sources:
- info.add_source(source)
- for code in self.support_code:
- info.add_support_code(code)
- info.add_support_code(self.py_to_c_code())
- info.add_support_code(self.c_to_py_code())
- for init_code in self.module_init_code:
- info.add_module_init_code(init_code)
- for macro in self.define_macros:
- info.add_define_macro(macro)
- for warning in self.warnings:
- info.add_warning(warning)
- for arg in self.extra_compile_args:
- info.add_extra_compile_arg(arg)
- for arg in self.extra_link_args:
- info.add_extra_link_arg(arg)
- return info
-
- def type_match(self,value):
- return type(value) in self.matching_types
-
- def get_var_type(self,value):
- return type(value)
-
- def type_spec(self,name,value):
- # factory
- new_spec = self.__class__()
- new_spec.name = name
- new_spec.var_type = self.get_var_type(value)
- return new_spec
-
- def template_vars(self,inline=0):
- d = {}
- d['type_name'] = self.type_name
- d['check_func'] = self.check_func
- d['c_type'] = self.c_type
- d['return_type'] = self.return_type
- d['to_c_return'] = self.to_c_return
- d['name'] = self.name
- d['py_var'] = self.py_variable()
- d['var_lookup'] = self.retrieve_py_variable(inline)
- code = 'convert_to_%(type_name)s(%(py_var)s,"%(name)s")' % d
- d['var_convert'] = code
- if self.use_ref_count:
- d['inc_ref_count'] = "Py_XINCREF(py_obj);"
- else:
- d['inc_ref_count'] = ""
- return d
-
- def py_to_c_code(self):
- return py_to_c_template % self.template_vars()
-
- def c_to_py_code(self):
- return simple_c_to_py_template % self.template_vars()
-
- def declaration_code(self,templatize = 0,inline=0):
- code = '%(py_var)s = %(var_lookup)s;\n' \
- '%(c_type)s %(name)s = %(var_convert)s;\n' % \
- self.template_vars(inline=inline)
- return code
-
- def cleanup_code(self):
- if self.use_ref_count:
- code = 'Py_XDECREF(%(py_var)s);\n' % self.template_vars()
- #code += 'printf("cleaning up %(py_var)s\\n");\n' % self.template_vars()
- else:
- code = ""
- return code
-
- def __repr__(self):
- msg = "(file:: name: %s)" % self.name
- return msg
- def __cmp__(self,other):
- #only works for equal
- result = -1
- try:
- result = cmp(self.name,other.name) or \
- cmp(self.__class__, other.__class__)
- except AttributeError:
- pass
- return result
-
-#----------------------------------------------------------------------------
-# Module Converter
-#----------------------------------------------------------------------------
-class module_converter(common_base_converter):
- def init_info(self):
- common_base_converter.init_info(self)
- self.type_name = 'module'
- self.check_func = 'PyModule_Check'
- # probably should test for callable classes here also.
- self.matching_types = [ModuleType]
-
-#----------------------------------------------------------------------------
-# String Converter
-#----------------------------------------------------------------------------
-class string_converter(common_base_converter):
- def init_info(self):
- common_base_converter.init_info(self)
- self.type_name = 'string'
- self.check_func = 'PyString_Check'
- self.c_type = 'std::string'
- self.return_type = 'std::string'
- self.to_c_return = "std::string(PyString_AsString(py_obj))"
- self.matching_types = [StringType]
- self.headers.append('<string>')
- def c_to_py_code(self):
- # !! Need to dedent returned code.
- code = """
- PyObject* string_to_py(std::string s)
- {
- return PyString_FromString(s.c_str());
- }
- """
- return code
-
-#----------------------------------------------------------------------------
-# Unicode Converter
-#----------------------------------------------------------------------------
-class unicode_converter(common_base_converter):
- def init_info(self):
- common_base_converter.init_info(self)
- self.type_name = 'unicode'
- self.check_func = 'PyUnicode_Check'
- # This isn't supported by gcc 2.95.3 -- MSVC works fine with it.
- #self.c_type = 'std::wstring'
- #self.to_c_return = "std::wstring(PyUnicode_AS_UNICODE(py_obj))"
- self.c_type = 'Py_UNICODE*'
- self.return_type = self.c_type
- self.to_c_return = "PyUnicode_AS_UNICODE(py_obj)"
- self.matching_types = [UnicodeType]
- #self.headers.append('<string>')
-
- def declaration_code(self,templatize = 0,inline=0):
- # since wstring doesn't seem to work everywhere, we need to provide
- # the length variable Nxxx for the unicode string xxx.
- code = '%(py_var)s = %(var_lookup)s;\n' \
- '%(c_type)s %(name)s = %(var_convert)s;\n' \
- 'int N%(name)s = PyUnicode_GET_SIZE(%(py_var)s);\n' \
- % self.template_vars(inline=inline)
-
-
- return code
-#----------------------------------------------------------------------------
-# File Converter
-#----------------------------------------------------------------------------
-class file_converter(common_base_converter):
- def init_info(self):
- common_base_converter.init_info(self)
- self.type_name = 'file'
- self.check_func = 'PyFile_Check'
- self.c_type = 'FILE*'
- self.return_type = self.c_type
- self.to_c_return = "PyFile_AsFile(py_obj)"
- self.headers = ['<stdio.h>']
- self.matching_types = [FileType]
-
- def c_to_py_code(self):
- # !! Need to dedent returned code.
- code = """
- PyObject* file_to_py(FILE* file, char* name, char* mode)
- {
- PyObject* py_obj = NULL;
- //extern int fclose(FILE *);
- return (PyObject*) PyFile_FromFile(file, name, mode, fclose);
- }
- """
- return code
-
-#----------------------------------------------------------------------------
-#
-# Scalar Number Conversions
-#
-#----------------------------------------------------------------------------
-
-# the following typemaps are for 32 bit platforms. A way to do this
-# general case? maybe ask numeric types how long they are and base
-# the decisions on that.
-
-#----------------------------------------------------------------------------
-# Standard Python numeric --> C type maps
-#----------------------------------------------------------------------------
-num_to_c_types = {}
-num_to_c_types[type(1)] = 'long'
-num_to_c_types[type(1.)] = 'double'
-num_to_c_types[type(1.+1.j)] = 'std::complex<double> '
-# !! hmmm. The following is likely unsafe...
-num_to_c_types[type(1L)] = 'longlong'
-
-#----------------------------------------------------------------------------
-# Numeric array Python numeric --> C type maps
-#----------------------------------------------------------------------------
-num_to_c_types['T'] = 'T' # for templates
-num_to_c_types['G'] = 'std::complex<longdouble> '
-num_to_c_types['F'] = 'std::complex<float> '
-num_to_c_types['D'] = 'std::complex<double> '
-num_to_c_types['g'] = 'longdouble'
-num_to_c_types['f'] = 'float'
-num_to_c_types['d'] = 'double'
-num_to_c_types['b'] = 'char'
-num_to_c_types['B'] = 'uchar'
-num_to_c_types['h'] = 'short'
-num_to_c_types['H'] = 'ushort'
-num_to_c_types['i'] = 'int'
-num_to_c_types['I'] = 'uint'
-
-# not strictly correct, but shoulld be fine fo numeric work.
-# add test somewhere to make sure long can be cast to int before using.
-num_to_c_types['l'] = 'long'
-num_to_c_types['L'] = 'ulong'
-
-num_to_c_types['q'] = 'longlong'
-num_to_c_types['Q'] = 'ulonglong'
-
-class scalar_converter(common_base_converter):
- def init_info(self):
- common_base_converter.init_info(self)
- self.warnings = ['disable: 4275', 'disable: 4101']
- self.headers = ['<complex>','<math.h>']
- self.use_ref_count = 0
-
-class int_converter(scalar_converter):
- def init_info(self):
- scalar_converter.init_info(self)
- self.type_name = 'int'
- self.check_func = 'PyInt_Check'
- self.c_type = 'long'
- self.return_type = 'long'
- self.to_c_return = "PyInt_AsLong(py_obj)"
- self.matching_types = [IntType]
-
-class long_converter(scalar_converter):
- def init_info(self):
- scalar_converter.init_info(self)
- # !! long to int conversion isn't safe!
- self.type_name = 'long'
- self.check_func = 'PyLong_Check'
- self.c_type = 'longlong'
- self.return_type = 'longlong'
- self.to_c_return = "(longlong) PyLong_AsLongLong(py_obj)"
- self.matching_types = [LongType]
-
-class float_converter(scalar_converter):
- def init_info(self):
- scalar_converter.init_info(self)
- # Not sure this is really that safe...
- self.type_name = 'float'
- self.check_func = 'PyFloat_Check'
- self.c_type = 'double'
- self.return_type = 'double'
- self.to_c_return = "PyFloat_AsDouble(py_obj)"
- self.matching_types = [FloatType]
-
-class complex_converter(scalar_converter):
- def init_info(self):
- scalar_converter.init_info(self)
- self.type_name = 'complex'
- self.check_func = 'PyComplex_Check'
- self.c_type = 'std::complex<double>'
- self.return_type = 'std::complex<double>'
- self.to_c_return = "std::complex<double>(PyComplex_RealAsDouble(py_obj),"\
- "PyComplex_ImagAsDouble(py_obj))"
- self.matching_types = [ComplexType]
-
-#----------------------------------------------------------------------------
-#
-# List, Tuple, and Dict converters.
-#
-# Based on SCXX by Gordon McMillan
-#----------------------------------------------------------------------------
-import os, c_spec # yes, I import myself to find out my __file__ location.
-local_dir,junk = os.path.split(os.path.abspath(c_spec.__file__))
-scxx_dir = os.path.join(local_dir,'scxx')
-
-class scxx_converter(common_base_converter):
- def init_info(self):
- common_base_converter.init_info(self)
- self.headers = ['"scxx/object.h"','"scxx/list.h"','"scxx/tuple.h"',
- '"scxx/dict.h"','<iostream>']
- self.include_dirs = [local_dir,scxx_dir]
- self.sources = [os.path.join(scxx_dir,'weave_imp.cpp'),]
-
-class list_converter(scxx_converter):
- def init_info(self):
- scxx_converter.init_info(self)
- self.type_name = 'list'
- self.check_func = 'PyList_Check'
- self.c_type = 'py::list'
- self.return_type = 'py::list'
- self.to_c_return = 'py::list(py_obj)'
- self.matching_types = [ListType]
- # ref counting handled by py::list
- self.use_ref_count = 0
-
-class tuple_converter(scxx_converter):
- def init_info(self):
- scxx_converter.init_info(self)
- self.type_name = 'tuple'
- self.check_func = 'PyTuple_Check'
- self.c_type = 'py::tuple'
- self.return_type = 'py::tuple'
- self.to_c_return = 'py::tuple(py_obj)'
- self.matching_types = [TupleType]
- # ref counting handled by py::tuple
- self.use_ref_count = 0
-
-class dict_converter(scxx_converter):
- def init_info(self):
- scxx_converter.init_info(self)
- self.type_name = 'dict'
- self.check_func = 'PyDict_Check'
- self.c_type = 'py::dict'
- self.return_type = 'py::dict'
- self.to_c_return = 'py::dict(py_obj)'
- self.matching_types = [DictType]
- # ref counting handled by py::dict
- self.use_ref_count = 0
-
-#----------------------------------------------------------------------------
-# Instance Converter
-#----------------------------------------------------------------------------
-class instance_converter(scxx_converter):
- def init_info(self):
- scxx_converter.init_info(self)
- self.type_name = 'instance'
- self.check_func = 'PyInstance_Check'
- self.c_type = 'py::object'
- self.return_type = 'py::object'
- self.to_c_return = 'py::object(py_obj)'
- self.matching_types = [InstanceType]
- # ref counting handled by py::object
- self.use_ref_count = 0
-
-#----------------------------------------------------------------------------
-# Catchall Converter
-#
-# catch all now handles callable objects
-#----------------------------------------------------------------------------
-class catchall_converter(scxx_converter):
- def init_info(self):
- scxx_converter.init_info(self)
- self.type_name = 'catchall'
- self.check_func = ''
- self.c_type = 'py::object'
- self.return_type = 'py::object'
- self.to_c_return = 'py::object(py_obj)'
- # ref counting handled by py::object
- self.use_ref_count = 0
- def type_match(self,value):
- return 1
-
-if __name__ == "__main__":
- x = list_converter().type_spec("x",1)
- print x.py_to_c_code()
- print
- print x.c_to_py_code()
- print
- print x.declaration_code(inline=1)
- print
- print x.cleanup_code()