Re: writing to a c_char_p received in a callback

Larry Bugbee <[email protected]> Sun, 10 Jul 2011 01:22:52 -0700
Newsgroups gmane.comp.python.ctypes
Message-ID <[email protected]>
> I have a callback function that would be defined like this in C:
> 
> 
> 
> #define MY_DATA = "abcdefg"
> 
> int set_data_cb(void *unused, char *buf, int* bufsize) {
>    (*bufsize) = (int)strlen(MY_DATA)
>    strncpy(buf, MY_DATA, (*bufsize))
> }
> 
> Of course this is simplified, but the idea is the caller is passing the
> callback func a pointer to a string, which the callback function is
> responsible for adding data to. I'm having an awfully hard time getting
> this to work with ctypes. It seems that ctypes is automatically
> converting my c_char_p into a normal python str, which of course does
> not allow me to update the original char* that was passed into the
> callback.
> 
> I've tried several different variations:
> 
> 1)      CB_FUNC_INPUT  =CFUNCTYPE(c_int, c_voidp, c_char_p,
> POINTER(ctypes.c_int))
> # This gives me a python str ... no good
> 
> 2)      class my_c_char_p(ctypes.c_char_p): pass
> CB_FUNC_INPUT  =CFUNCTYPE(c_int, c_voidp, my_c_char_p,
> POINTER(ctypes.c_int))
> # this gives me a my_c_char_p object, but updating the value property
> doesn't seem to get my data back to the caller
> 
> 3)      CB_FUNC_INPUT  =CFUNCTYPE(c_int, c_voidp, POINTER(c_char_p),
> POINTER(ctypes.c_int))
> # this gives me a pointer, but settings contents.value also does not get
> my data back to the caller
> 
> 4)      CB_FUNC_INPUT  =CFUNCTYPE(c_int, c_voidp, c_void_p,
> POINTER(ctypes.c_int))
> # argh, this gives me a long, not a pointer. (I was hoping I could just
> cast it, but no luck)
> 
> I've googled this to death, but either I have not found the magic
> combination of search terms, or the answer is so obvious that nobody
> else has had this problem.
> 
> Any help would be appreciated!
> 
> TIA
> 
> -Matt

Consider something like this.  (tested on OSX)

C lib:
-------
#include "string.h"
#define MY_DATA  "abcdefg"
void set_data_cb(void *unused, char *buf, int *bufsize) {
    // should test *bufsize > strlen(MY_DATA)
    strncpy(buf, MY_DATA, strlen(MY_DATA));
    buf[strlen(MY_DATA)]='\0';
}

Python pgm:
------------
from ctypes import *
LIB = CDLL('libxxx.so')
bufsize = c_int(20)
buf     = c_buffer(bufsize.value)
LIB.set_data_cb(None, buf, bufsize)
print '  %s, len=%d' % (buf.value, len(buf.value))

OSX compilation and execution:
-------------------------------
gcc -dynamiclib -o libxxx.so libxxx.c
python pgm.py 


Larry




------------------------------------------------------------------------------
All of the data generated in your IT infrastructure is seriously valuable.
Why? It contains a definitive record of application performance, security 
threats, fraudulent activity, and more. Splunk takes this data and makes 
sense of it. IT sense. And common sense.
http://p.sf.net/sfu/splunk-d2d-c2