Michael WS
Michael WS

Reputation: 2617

cython create string with nogil

I would like to create a c++ string in a nogil function in a file that would be cimported via pxd. If I define, string output = "" or string output = string("blah"), this uses the python interpreter. Is there a way to define the a string so that the compiler writes in the cython cpp file:

std::string val = "blah";

Basically have this:

from libcpp.string cimport string
cdef string my_func() nogil:
   cdef:
      string output = "blah"
  ....
  return output

Upvotes: 3

Views: 781

Answers (1)

ev-br
ev-br

Reputation: 26040

%%cython -a

#distutils: language = c++

from libcpp.string cimport string

cdef string my_func() nogil:
    cdef:
        char* c_str = 'blah'
        string output = <string>(c_str)
    return output


def py_call():
    return my_func()

Then calling py_call() gives b'blah', i.e. a bytes object.

EDIT: Here's the generated C++ code:

+08:         char* c_str = 'blah'
  __pyx_v_c_str = ((char *)"blah");
+09:         string output = <string>(c_str)
  __pyx_v_output = ((std::string)__pyx_v_c_str);

So it literally casts char* to std::string.

An alternative is then to invoke the constructor from char*:

cdef:
    char* c_str = 'blah'
    string output = string(c_str)

which generates

+08:         char* c_str = 'blah'
  __pyx_v_c_str = ((char *)"blah");
+09:         string output = string(c_str, 4)
  try {
    __pyx_t_1 = std::string(__pyx_v_c_str, 4);
  } catch(...) {
    #ifdef WITH_THREAD
    PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();
    #endif
    __Pyx_CppExn2PyErr();
    #ifdef WITH_THREAD
    PyGILState_Release(__pyx_gilstate_save);
    #endif
    __PYX_ERR(0, 9, __pyx_L1_error)
  }
  __pyx_v_output = __pyx_t_1;

which looks better.

Upvotes: 3

Related Questions