Search code examples
cythonstrcat

strncat use in cython


for learning purposes I am trying to use strncat in cython within a class.

I do:

from libc.stdlib cimport free

cdef extern from "<string.h>":
    char *strncat(char *pto, const char **pfrom, size_t_size)
    size_t strlen   (const char *s)

cdef class test:
    cdef:
        char *palabra
        #size_t len_palabra
    
    def __cinit__(self, char *Palabra):
        self.palabra = Palabra
    
    cdef append_palabra(self, char *other_palabra):
        strncat(self.palabra, &other_palabra, strlen(other_palabra))
        print(other_palabra)
           
    def manipulate_palabra(self, char *other_palabra):
        self.append_palabra(other_palabra)
        print(self.palabra)
        
    def __dealloc__(self):
        free(self.palabra)
    
        
a = test(b'first ')
a.manipulate_palabra(b'second')

The print statements throw:

b'second'
b'first H\xc3-\xcd\xa9\x7f'
  1. How should I obtain b'first second' ?
  2. I purposely bring up the whole class to hear critics and comments as I am almost illiterate in Cython.

Thank you!


Solution

  • Your issue was that you'd defined:

    char *strncat(char *pto, const char **pfrom, size_t_size)
    

    but the actual signature is

    char *strncat(char *pto, const char *pfrom, size_t_size)
    

    I suspect this should have at least generated a warning at the C compilation stage that it's worth taking seriously.

    Cython does wrap most of the C standard library so the simplest solution would be

    from libc.string cimport strncat, stolen
    

    There's nothing magical about the Cython wrappings - they're provided for convenience but the don't do anything that you can't write yourself (at least for C, this isn't quite true for the C++ wrappings). However the good thing about them is that they are tested, so you can be reasonably confident that they're right.