Commit 51a47ebe authored by Robert Bradshaw's avatar Robert Bradshaw

Allow custom std::string alternatives.

parent b517d0c1
...@@ -2966,9 +2966,9 @@ class CStructOrUnionType(CType): ...@@ -2966,9 +2966,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)
cpp_string_conversions = ("std::string",)
builtin_cpp_conversions = ("std::string", builtin_cpp_conversions = ("std::pair",
"std::pair",
"std::vector", "std::list", "std::vector", "std::list",
"std::set", "std::unordered_set", "std::set", "std::unordered_set",
"std::map", "std::unordered_map") "std::map", "std::unordered_map")
...@@ -3000,7 +3000,7 @@ class CppClassType(CType): ...@@ -3000,7 +3000,7 @@ class CppClassType(CType):
self.templates = templates self.templates = templates
self.template_type = template_type self.template_type = template_type
self.specializations = {} self.specializations = {}
self.is_cpp_string = cname == 'std::string' self.is_cpp_string = cname in cpp_string_conversions
def use_conversion_utility(self, from_or_to): def use_conversion_utility(self, from_or_to):
pass pass
...@@ -3014,7 +3014,7 @@ class CppClassType(CType): ...@@ -3014,7 +3014,7 @@ class CppClassType(CType):
def create_from_py_utility_code(self, env): def create_from_py_utility_code(self, env):
if self.from_py_function is not None: if self.from_py_function is not None:
return True return True
if self.cname in builtin_cpp_conversions: if self.cname in builtin_cpp_conversions or self.cname in cpp_string_conversions:
X = "XYZABC" X = "XYZABC"
tags = [] tags = []
declarations = ["cdef extern from *:"] declarations = ["cdef extern from *:"]
...@@ -3055,12 +3055,16 @@ class CppClassType(CType): ...@@ -3055,12 +3055,16 @@ class CppClassType(CType):
declarations.append( declarations.append(
" cdef %s %s_from_py '%s' (object) except %s" % ( " cdef %s %s_from_py '%s' (object) except %s" % (
X[ix], X[ix], T.from_py_function, except_clause)) X[ix], X[ix], T.from_py_function, except_clause))
if self.cname in cpp_string_conversions:
cls = 'string'
else:
cls = self.cname[5:] cls = self.cname[5:]
cname = '__pyx_convert_%s_from_py_%s' % (cls, '____'.join(tags)) cname = '__pyx_convert_%s_from_py_%s' % (cls, '____'.join(tags))
context = { context = {
'template_type_declarations': '\n'.join(declarations), 'template_type_declarations': '\n'.join(declarations),
'cname': cname, 'cname': cname,
'maybe_unordered': self.maybe_unordered(), 'maybe_unordered': self.maybe_unordered(),
'type': self.cname,
} }
from .UtilityCode import CythonUtilityCode from .UtilityCode import CythonUtilityCode
env.use_utility_code(CythonUtilityCode.load(cls.replace('unordered_', '') + ".from_py", "CppConvert.pyx", context=context)) env.use_utility_code(CythonUtilityCode.load(cls.replace('unordered_', '') + ".from_py", "CppConvert.pyx", context=context))
...@@ -3070,7 +3074,7 @@ class CppClassType(CType): ...@@ -3070,7 +3074,7 @@ class CppClassType(CType):
def create_to_py_utility_code(self, env): def create_to_py_utility_code(self, env):
if self.to_py_function is not None: if self.to_py_function is not None:
return True return True
if self.cname in builtin_cpp_conversions: if self.cname in builtin_cpp_conversions or self.cname in cpp_string_conversions:
X = "XYZABC" X = "XYZABC"
tags = [] tags = []
declarations = ["cdef extern from *:"] declarations = ["cdef extern from *:"]
...@@ -3084,12 +3088,16 @@ class CppClassType(CType): ...@@ -3084,12 +3088,16 @@ class CppClassType(CType):
declarations.append( declarations.append(
" cdef object %s_to_py '%s' (%s)" % ( " cdef object %s_to_py '%s' (%s)" % (
X[ix], T.to_py_function, X[ix])) X[ix], T.to_py_function, X[ix]))
if self.cname in cpp_string_conversions:
cls = 'string'
else:
cls = self.cname[5:] cls = self.cname[5:]
cname = "__pyx_convert_%s_to_py_%s" % (cls, "____".join(tags)) cname = "__pyx_convert_%s_to_py_%s" % (cls, "____".join(tags))
context = { context = {
'template_type_declarations': '\n'.join(declarations), 'template_type_declarations': '\n'.join(declarations),
'cname': cname, 'cname': cname,
'maybe_unordered': self.maybe_unordered(), 'maybe_unordered': self.maybe_unordered(),
'type': self.cname,
} }
from .UtilityCode import CythonUtilityCode from .UtilityCode import CythonUtilityCode
env.use_utility_code(CythonUtilityCode.load(cls.replace('unordered_', '') + ".to_py", "CppConvert.pyx", context=context)) env.use_utility_code(CythonUtilityCode.load(cls.replace('unordered_', '') + ".to_py", "CppConvert.pyx", context=context))
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
#################### string.from_py #################### #################### string.from_py ####################
cdef extern from *: cdef extern from *:
cdef cppclass string "std::string": cdef cppclass string "{{type}}":
string() string()
string(char* c_str, size_t size) string(char* c_str, size_t size)
cdef char* __Pyx_PyObject_AsStringAndSize(object, Py_ssize_t*) except NULL cdef char* __Pyx_PyObject_AsStringAndSize(object, Py_ssize_t*) except NULL
...@@ -21,7 +21,7 @@ cdef string {{cname}}(object o) except *: ...@@ -21,7 +21,7 @@ cdef string {{cname}}(object o) except *:
#cimport cython #cimport cython
#from libcpp.string cimport string #from libcpp.string cimport string
cdef extern from *: cdef extern from *:
cdef cppclass string "std::string": cdef cppclass string "{{type}}":
char* data() char* data()
size_t size() size_t size()
cdef object __Pyx_PyObject_FromStringAndSize(char*, size_t) cdef object __Pyx_PyObject_FromStringAndSize(char*, size_t)
......
# tag: cpp
PYTHON setup.py build_ext --inplace
PYTHON -c "import a; a.test_convert()"
######## setup.py ########
from Cython.Build.Dependencies import cythonize
from Cython.Compiler import PyrexTypes
PyrexTypes.cpp_string_conversions += ("MyString",)
from distutils.core import setup
setup(
ext_modules = cythonize("*.pyx"),
)
######## my_string.cpp ########
#include <string>
class MyString {
public:
MyString() { }
MyString(const char* data, size_t size) : value_(data, size) { }
const char* data() const { return value_.data(); }
const size_t size() const { return value_.size(); }
private:
std::string value_;
};
######## a.pyx ########
# distutils: language = c++
cdef extern from "my_string.cpp":
cdef cppclass MyString:
pass
def do_convert(MyString value):
return value
def test_convert():
assert do_convert("abc") == "abc"
assert do_convert("ab\0c") == "ab\0c"
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