Stuck on some basic Cython here - what's a canonical and efficient way to define an an array of strings in Cython?  Specifically, I want to define a fixed-length constant array of char.  (Please note that I would prefer not to bring in NumPy at this point.)
In C this would be:
/* cletters.c */
#include <stdio.h>
int main(void)
{
    const char *headers[3] = {"to", "from", "sender"};
    int i;
    for (i = 0; i < 3; i++)
        printf("%s\n", headers[i]);
}
Attempt in Cython:
# cython: language_level=3
# letters.pyx
cpdef main():
    cdef const char *headers[3] = {"to", "from", "sender"}
    print(headers)
However, this gives:
(cy) $ python3 ./setup.py build_ext --inplace --quiet
cpdef main():
    cdef const char *headers[3] = {"to", "from", "sender"}
                               ^
------------------------------------------------------------
letters.pyx:5:32: Syntax error in C variable declaration
String literals Cython understands all Python string type prefixes: b'bytes' for byte strings. u'text' for Unicode strings. f'formatted {value}' for formatted Unicode string literals as defined by PEP 498 (added in Cython 0.24)
You need two lines:
%%cython
cpdef main():
    cdef const char *headers[3] 
    headers[:] = ['to','from','sender`]       
    print(headers)
Somewhat counterintuitive is than one assigns unicode-strings (Python3!) to char*. That is one of Cython's quirks. On the other hand, while initializing everything with only one value, bytes-object is needed:
%%cython
cpdef main():
    cdef const char *headers[3] 
    headers[:] = b'init_value`  ## unicode-string 'init_value' doesn't work.     
    print(headers)
Another alternative is the following oneliner:
%%cython
cpdef main():
    cdef const char **headers=['to','from','sender`]
    print(headers[0], headers[1], headers[2])
which is not exactly the same as above and leads to the following C-code:
  char const **__pyx_v_headers;
  ...
  char const *__pyx_t_1[3];
  ...
  __pyx_t_1[0] = ((char const *)"to");
  __pyx_t_1[1] = ((char const *)"from");
  __pyx_t_1[2] = ((char const *)"sender");
  __pyx_v_headers = __pyx_t_1;
__pyx_v_headers is of type char ** and downside is, that print(headers)no longer works out of the box.
For python3 Unicode strings, this is possible-
cdef Py_UNICODE* x[2] 
x = ["hello", "worlᏪd"]
or
cdef Py_UNICODE** x
x = ["hello", "worlᏪd"]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With