summaryrefslogtreecommitdiff
path: root/scipy/weave/cpp_namespace_spec.py
blob: bfd67d2f31cd96502e87f5e0c1d755fa915d0f4c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
""" This converter works with classes protected by a namespace with
    SWIG pointers (Python strings).  To use it to wrap classes in
    a C++ namespace called "ft", use the following:
    
    class ft_converter(cpp_namespace_converter):
        namespace = 'ft::'        
"""

from weave import common_info
from weave import  base_info
from weave.base_spec import base_converter

cpp_support_template = \
"""
static %(cpp_struct)s* convert_to_%(cpp_clean_struct)s(PyObject* py_obj,char* name)
{
    %(cpp_struct)s *cpp_ptr = 0;
    char* str = PyString_AsString(py_obj);
    if (!str)
        handle_conversion_error(py_obj,"%(cpp_struct)s", name);
    // work on this error reporting...
    //std::cout << "in:" << name << " " py_obj << std::endl;
    if (SWIG_GetPtr(str,(void **) &cpp_ptr,"_%(cpp_struct)s_p"))
    {
        handle_conversion_error(py_obj,"%(cpp_struct)s", name);
    }
    //std::cout << "out:" << name << " " << str << std::endl;
    return cpp_ptr;
}    

static %(cpp_struct)s* py_to_%(cpp_clean_struct)s(PyObject* py_obj,char* name)
{
    %(cpp_struct)s *cpp_ptr;
    char* str = PyString_AsString(py_obj);
    if (!str)
        handle_conversion_error(py_obj,"%(cpp_struct)s", name);
    // work on this error reporting...
    if (SWIG_GetPtr(str,(void **) &cpp_ptr,"_%(cpp_struct)s_p"))
    {
        handle_conversion_error(py_obj,"%(cpp_struct)s", name);
    }
    return cpp_ptr;
}    

std::string %(cpp_clean_struct)s_to_py( %(cpp_struct)s* cpp_ptr)
{
    char ptr_string[%(ptr_string_len)s]; 
    SWIG_MakePtr(ptr_string, cpp_ptr, "_%(cpp_struct)s_p");
    return std::string(ptr_string);
}              

"""        

class cpp_namespace_converter(base_converter):
    _build_information = [common_info.swig_info()]
    def __init__(self,class_name=None):
        self.type_name = 'unkown cpp_object'
        self.name =  'no name'        
        if class_name:
            # customize support_code for whatever type I was handed.
            clean_name = class_name.replace('::','_')
            clean_name = clean_name.replace('<','_')
            clean_name = clean_name.replace('>','_')
            clean_name = clean_name.replace(' ','_')
            # should be enough for 64 bit machines
            str_len = len(clean_name) + 20 
            vals = {'cpp_struct': class_name,
                    'cpp_clean_struct': clean_name,
                    'ptr_string_len': str_len }
            specialized_support = cpp_support_template % vals
            custom = base_info.base_info()
            custom._support_code = [specialized_support]
            self._build_information = self._build_information + [custom]
            self.type_name = class_name

    def type_match(self,value):
        try:
            cpp_ident = value.split('_')[2]
            if cpp_ident.find(self.namespace) != -1:
                return 1
        except:
            pass
        return 0
            
    def type_spec(self,name,value):
        # factory
        ptr_fields = value.split('_')
        class_name = '_'.join(ptr_fields[2:-1])
        new_spec = self.__class__(class_name)
        new_spec.name = name        
        return new_spec
        
    def declaration_code(self,inline=0):
        type = self.type_name
        clean_type = type.replace('::','_')
        name = self.name
        var_name = self.retrieve_py_variable(inline)
        template = '%(type)s *%(name)s = '\
                   'convert_to_%(clean_type)s(%(var_name)s,"%(name)s");\n'
        code = template % locals()
        return code
        
    def __repr__(self):
        msg = "(%s:: name: %s)" % (self.type_name,self.name)
        return msg
    def __cmp__(self,other):
        #only works for equal
        return cmp(self.name,other.name) or \
               cmp(self.__class__, other.__class__) or \
               cmp(self.type_name,other.type_name)