char * in parameters and results

759 views
Skip to first unread message

Alexey Poryadin

unread,
Nov 7, 2014, 1:56:11 PM11/7/14
to pytho...@googlegroups.com
char * in parameters and results

Hi all!
I found this library very interesting and useful for me. I have question. May be it is stupid question,  I only start to touch this.  I am interesting when calling C function with parameter const char * or callback returns poiner to char array , it is creating copy of data from python string or it is making reference? for example:

    @ffi.callback("const char*(*)(int, size_t*)")
    def callback(fd, ptr_size):
        print("... callback", fd, ptr_size[0])
        data = next_callback(fd)  // it's returns bytes
        ptr_size[0] = len(data)
        cdata = ffi.new("char[]", data)  // cdata contain copy or ref  of bytes in data?
        return cdata

Excuse my poor English.

Armin Rigo

unread,
Nov 9, 2014, 3:21:17 AM11/9/14
to pytho...@googlegroups.com
Hi,

On 7 November 2014 19:56, Alexey Poryadin <alexey....@gmail.com> wrote:
> cdata = ffi.new("char[]", data) // cdata contain copy or ref of
> bytes in data?

With ffi.new(), the cdata contains a copy of the bytes in data.

> return cdata

This doesn't work: you can't have a callback returning a `char *` in
this way. The reason is that the cdata is garbage as soon as we leave
the function, and thus possibly deallocated, before the caller gets to
look at the bytes. You have the same problem as C functions that want
to return a `char *` string: you can't declare and fill a local array
of chars and then return a pointer to it.

You need to store the `cdata` object somewhere globally, and keep it
alive as long as the C caller of that callback may inspect it. How
long this is must be specified by this C code.


A bientôt,

Armin.

Antonio Cuni

unread,
Nov 11, 2014, 6:47:13 AM11/11/14
to python-cffi
On Sun, Nov 9, 2014 at 9:20 AM, Armin Rigo <ar...@tunes.org> wrote:
 
>         return cdata

This doesn't work: you can't have a callback returning a `char *` in
this way.  The reason is that the cdata is garbage as soon as we leave
the function, and thus possibly deallocated, before the caller gets to
look at the bytes.  You have the same problem as C functions that want
to return a `char *` string: you can't declare and fill a local array
of chars and then return a pointer to it.

You need to store the `cdata` object somewhere globally, and keep it
alive as long as the C caller of that callback may inspect it.  How
long this is must be specified by this C code.

​or, as an alternative: you can explicitly malloc the buffer to hold the string, but then you need to ensure that the caller will take care of freeing it:

import cffi

ffi = cffi.FFI()
ffi.cdef("""
    void* malloc(size_t s);
    void free(void* ptr);
    void strcpy(char* dest, char* src);
    size_t strlen(char* s);
""")

lib = ffi.verify("""
    #include <stdlib.h>
    #include <string.h>
""")

def foo():
    data = ffi.new('char[]', 'foobar')
    n = lib.strlen(data)
    buf = ffi.cast('char*', lib.malloc(n+1))
    lib.strcpy(buf, data)
    return buf

mydata = foo()
print ffi.string(mydata)
lib.free(mydata)


 

Reply all
Reply to author
Forward
0 new messages