Commit 1aa49b25 authored by Robert Bradshaw's avatar Robert Bradshaw

First pass at C++ stl conversion.

parent 75c52f53
...@@ -7084,7 +7084,7 @@ class AmpersandNode(ExprNode): ...@@ -7084,7 +7084,7 @@ class AmpersandNode(ExprNode):
def analyse_types(self, env): def analyse_types(self, env):
self.operand.analyse_types(env) self.operand.analyse_types(env)
argtype = self.operand.type argtype = self.operand.type
if not (argtype.is_cfunction or self.operand.is_addressable()): if not (argtype.is_cfunction or argtype.is_reference or self.operand.is_addressable()):
if argtype.is_memoryviewslice: if argtype.is_memoryviewslice:
self.error("Cannot take address of memoryview slice") self.error("Cannot take address of memoryview slice")
else: else:
......
...@@ -22,7 +22,16 @@ class BaseType(object): ...@@ -22,7 +22,16 @@ class BaseType(object):
return "((%s)%s)" % (self.declaration_code(""), expr_code) return "((%s)%s)" % (self.declaration_code(""), expr_code)
def specialization_name(self): def specialization_name(self):
return self.declaration_code("").replace(" ", "__") # This is not entirely robust.
safe = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789'
all = []
for c in self.declaration_code("").replace(" ", "__"):
if c in safe:
all.append(c)
else:
all.append('_%x_' % ord(c))
print self.declaration_code(""), ''.join(all)
return ''.join(all)
def base_declaration_code(self, base_code, entity_code): def base_declaration_code(self, base_code, entity_code):
if entity_code: if entity_code:
...@@ -2978,6 +2987,9 @@ class CStructOrUnionType(CType): ...@@ -2978,6 +2987,9 @@ class CStructOrUnionType(CType):
return expr_code return expr_code
return super(CStructOrUnionType, self).cast_code(expr_code) return super(CStructOrUnionType, self).cast_code(expr_code)
builtin_cpp_conversions = ("std::string", "std::vector", "std::set", "std::map", "std::pair")
class CppClassType(CType): class CppClassType(CType):
# name string # name string
# cname string # cname string
...@@ -3001,6 +3013,47 @@ class CppClassType(CType): ...@@ -3001,6 +3013,47 @@ class CppClassType(CType):
self.template_type = template_type self.template_type = template_type
self.specializations = {} self.specializations = {}
def use_conversion_utility(self, from_or_to):
pass
def create_from_py_utility_code(self, env):
if self.from_py_function is not None:
return True
if self.cname in builtin_cpp_conversions:
tags = []
context = {}
for ix, T in enumerate(self.templates or []):
if not T.create_from_py_utility_code(env):
return False
tags.append(T.specialization_name())
context["T%s" % ix] = T.declaration_code("", for_display=True)
cls = self.cname[5:]
cname = "__pyx_convert_%s_from_py_%s" % (cls, "____".join(tags))
context['cname'] = cname
from UtilityCode import CythonUtilityCode
env.use_utility_code(CythonUtilityCode.load(cls + ".from_py", "CppConvert.pyx", context=context))
self.from_py_function = cname
return True
def create_to_py_utility_code(self, env):
if self.to_py_function is not None:
return True
if self.cname in builtin_cpp_conversions:
tags = []
context = {}
for ix, T in enumerate(self.templates or []):
if not T.create_to_py_utility_code(env):
return False
tags.append(T.specialization_name())
context["T%s" % ix] = T.declaration_code("", for_display=True)
cls = self.cname[5:]
cname = "__pyx_convert_%s_to_py_%s" % (cls, "____".join(tags))
context['cname'] = cname
from UtilityCode import CythonUtilityCode
env.use_utility_code(CythonUtilityCode.load(cls + ".to_py", "CppConvert.pyx", context=context))
self.to_py_function = cname
return True
def specialize_here(self, pos, template_values = None): def specialize_here(self, pos, template_values = None):
if self.templates is None: if self.templates is None:
error(pos, "'%s' type is not a template" % self); error(pos, "'%s' type is not a template" % self);
...@@ -3035,7 +3088,11 @@ class CppClassType(CType): ...@@ -3035,7 +3088,11 @@ class CppClassType(CType):
if self.templates: if self.templates:
template_strings = [param.declaration_code('', for_display, None, pyrex) template_strings = [param.declaration_code('', for_display, None, pyrex)
for param in self.templates] for param in self.templates]
templates = "<%s>" % ",".join(template_strings) if for_display:
brackets = "[%s]"
else:
brackets = "<%s>"
templates = brackets % ",".join(template_strings)
if templates[-2:] == ">>": if templates[-2:] == ">>":
templates = templates[:-2] + "> >" templates = templates[:-2] + "> >"
else: else:
......
# TODO: Figure out how many of the pass-by-value copies the compiler can eliminate.
#################### string.from_py ####################
cdef extern from *:
cdef cppclass string "std::string":
string(char* c_str, size_t size)
@cname("{{cname}}")
cdef string {{cname}}(object o) except *:
return string(<char*>o, len(o))
#################### string.to_py ####################
#cimport cython
#from libcpp.string cimport string
cdef extern from *:
cdef cppclass string "const std::string":
char* c_str()
size_t size()
@cname("{{cname}}")
cdef object {{cname}}(string& s):
return s.c_str()[:s.size()]
#################### vector.from_py ####################
cdef extern from *:
cdef cppclass vector "std::vector" [T]:
void push_back(T&)
@cname("{{cname}}")
cdef vector[{{T0}}] {{cname}}(object o) except *:
cdef vector[{{T0}}] v
for item in o:
v.push_back(item)
return v
#################### vector.to_py ####################
cdef extern from *:
cdef cppclass vector "const std::vector" [T]:
size_t size()
T& operator[](size_t)
@cname("{{cname}}")
cdef object {{cname}}(vector[{{T0}}]& v):
return [v[i] for i in range(v.size())]
#################### list.from_py ####################
cdef extern from *:
cdef cppclass cpp_list "std::list" [T]:
void push_back(T&)
@cname("{{cname}}")
cdef cpp_list[{{T0}}] {{cname}}(object o) except *:
cdef cpp_list[{{T0}}] l
for item in o:
l.push_back(item)
return l
#################### list.to_py ####################
cdef extern from *:
cdef cppclass cpp_list "std::list" [T]:
cppclass const_iterator:
T& operator*()
const_iterator operator++()
bint operator!=(const_iterator)
const_iterator begin()
const_iterator end()
cdef cppclass const_cpp_list "const std::list" [T] (cpp_list)
@cname("{{cname}}")
cdef object {{cname}}(const_cpp_list[{{T0}}]& v):
o = []
cdef cpp_list[{{T0}}].const_iterator iter = s.begin()
while iter != s.end():
o.append(cython.operator.dereference(iter))
cython.operator.preincrement(iter)
return o
#################### set.from_py ####################
cdef extern from *:
cdef cppclass set "std::set" [T]:
void insert(T&)
@cname("{{cname}}")
cdef set[{{T0}}] {{cname}}(object o) except *:
cdef set[{{T0}}] s
for item in o:
s.insert(item)
return s
#################### set.to_py ####################
cimport cython
cdef extern from *:
cdef cppclass cpp_set "std::set" [T]:
cppclass const_iterator:
T& operator*()
const_iterator operator++()
bint operator!=(const_iterator)
const_iterator begin()
const_iterator end()
cdef cppclass const_cpp_set "const std::set" [T](cpp_set):
pass
@cname("{{cname}}")
cdef object {{cname}}(const_cpp_set[{{T0}}]& s):
o = set()
cdef cpp_set[{{T0}}].const_iterator iter = s.begin()
while iter != s.end():
o.add(cython.operator.dereference(iter))
cython.operator.preincrement(iter)
return o
#################### pair.from_py ####################
cdef extern from *:
cdef cppclass pair "std::pair" [T, U]:
pair(T&, U&)
@cname("{{cname}}")
cdef pair[{{T0}},{{T1}}] {{cname}}(object o) except *:
x, y = o
return pair[{{T0}},{{T1}}](x, y)
#################### pair.to_py ####################
cdef extern from *:
cdef cppclass pair "const std::pair" [T, U]:
T first
U second
@cname("{{cname}}")
cdef object {{cname}}(pair[{{T0}},{{T1}}]& p):
return p.first, p.second
#################### map.from_py ####################
cdef extern from *:
cdef cppclass pair "std::pair" [T, U]:
pair(T&, U&)
cdef cppclass map "std::map" [T, U]:
void insert(pair[T, U]&)
cdef cppclass pair "std::pair" [T, U]:
pass
cdef cppclass vector "std::vector" [T]:
pass
@cname("{{cname}}")
cdef map[{{T0}},{{T1}}] {{cname}}(object o) except *:
cdef dict d = o
cdef map[{{T0}},{{T1}}] m
for key, value in d.iteritems():
m.insert(pair[{{T0}},{{T1}}](<{{T0}}>key, <{{T1}}>value))
return m
#################### map.to_py ####################
# TODO: Work out const so that this can take a const
# reference rather than pass by value.
cimport cython
cdef extern from *:
cdef cppclass map "std::map" [T, U]:
cppclass value_type:
T first
U second
cppclass iterator:
value_type& operator*()
iterator operator++()
bint operator!=(iterator)
iterator begin()
iterator end()
@cname("{{cname}}")
cdef object {{cname}}(map[{{T0}},{{T1}}] s):
o = {}
cdef map[{{T0}},{{T1}}].value_type *key_value
cdef map[{{T0}},{{T1}}].iterator iter = s.begin()
while iter != s.end():
key_value = &cython.operator.dereference(iter)
o[key_value.first] = key_value.second
cython.operator.preincrement(iter)
return o
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment