I think your issue is with constness, not references. Cython doesn't
yet have any support for const (which is a mess). Probably the easiest
is to write a simple utility function that converts from std::string
to const std::string, or references thereof.
- Robert
Alas, if you could easily write something like this in Cython, you
wouldn't need to be writing int ;).
What I would do is write a C++ file util.cpp with the necessary
functions, and then do
cdef extern from "util.cpp":
...
It is possible to do such a thing in Cython itself, using cnames (see
the old C++ wrapping guides for how this works...)
- Robert
Hi,
I have come up with this:
#cuserconfig.pxd
cdef extern from "user.h":
ctypedef char *stdstringr "const std::string&"
cdef cppclass stringclass "std::string":
void stringclass()
char *c_str()
int get_avatar_name(stdstringr id, stringclass result)
#userconfig.pyx
cimport cuserconfig as C
def get_avatar_name(char *input):
cdef C.stringclass s = C.stringclass()
cdef int ret = C.get_avatar_name(input, s)
return ret, s.c_str()
I made a toy implementation of get_avatar_name() to test with:
//user.cpp
int get_avatar_name(const std::string & id, std::string &result)
{
static std::string s("hello world");
printf("%s\n", id.c_str());
result = s;
return 7;
}
and...
Python 2.6.5 (r265:79063, Jun 12 2010, 17:07:01)
[GCC 4.3.4 20090804 (release) 1] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from userconfig import *
>>> results = get_avatar_name("cython")
cython
>>> print results
(7, 'hello world')
>>>
I have found myself using this sort of pattern a few times myself
ctypedef char *stdstringr "const std::string&"
which allows Cython to produce code that works based on the underlying
type's ability to implicitly construct/coerce, along with the
apparently standard Cython practice of passing by value where a
reference is actually the function's argument signature, and adding
the constness even though Cython doesn't understand const.
This might not be a complete solution for you I realise, but is this
idea any help?
Paul
You're welcome. I'm glad it worked out for you, and I do use the same
technique myself in some code that will soon move from prototye to
production. However, it's effectively telling Cython a little white
lie, and I am a little bit uncomfortable with it.
ctypedef char *stdstringr "const std::string&"
Translates to: "A const std:string reference is a non-const char
pointer". Patently not true, even though it tricks the generated code
into working very nicely and allows for terse and elegant (imho)
Cython code.
It makes Cython a little bit less opaque, and we start to write Cython
code with foreknowledge of what C code the compiler will produce. It
sounds like the kind of thing that might break in a future revision.
Nevertheless it's such a useful feature to be able to exploit, that
I'd be interested to hear a Cython developer's take on it.
On a slightly related note, since this technique relies on implicit
type coercions, I have seen in some of the generated C code that a lot
casts are used, and that they are always plain C-style ones. Would it
be an easy change to the code to have these produced as static_cast
(perhaps optionally dynamic_cast) when --cplus mode is used? I have
had occasional run-time errors, I'm pretty sure, that were to do with
forced type coercions that must have ended up as a reinterpret_cast
type of operation at run time. If these could be made C++-style with
--cplus enabled, the compiler might be able to spot problems and issue
errors or warnings.
Paul