drlolly
drlolly

Reputation: 194

How set a C char** pointer in Python

I want to set a C char** pointer, called results, in Python. The variable is in a dll I have loaded. I want to set results so that it points to a string in Python. I want to get the string I created in Python (or at least a copy of it since ctypes does a lot of copying) to be pointed to by the C variable results. So I have in Python product_class = (ctypes.c_char_p)(b"321"). I want to set results to the value "321".

Here is the code I have written. It does not work. It does not even change the C-variable results.

# py_parse_pdl_func function is a callback which is called from a c dll which has been loaded into the python prorgram.
# Here is the declaration of the callback in c
# typedef int (*tsl_pdl_cb_t)(void *pz_prv, const char **results, const char* query);
# so am trying to set results to point to a string "321"


def py_parse_pdl_func(pz_prv, py_results, query):
    global product_class_void
    product_class = (ctypes.c_char_p)(b"321")
    product_class_void = ctypes.cast(product_class, ctypes.c_void_p)
    py_results.contents = ctypes.c_long(product_class_void.value)
  
    return 1

Upvotes: 0

Views: 176

Answers (1)

Mark Tolonen
Mark Tolonen

Reputation: 177471

Here's a reproducible example. You may need to keep a reference to the string returned since Python could deallocate it at any time.

test.c

#include <stdio.h>

typedef int (*tsl_pdl_cb_t)(void *pz_prv, const char **results, const char* query);

__declspec(dllexport)
int function_using_callback(tsl_pdl_cb_t callback) {
    char* results = NULL;
    int retval = 0;

    if(callback)
        retval = callback(NULL, &results, "the query");
    printf("results = '%s'\n", results);
    return retval;
}

test.py

import ctypes as ct

CALLBACK = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.POINTER(ct.c_char_p), ct.c_char_p)

dll = ct.CDLL('./test')
dll.function_using_callback.argtypes = CALLBACK,
dll.function_using_callback.restype = ct.c_int

@CALLBACK
def py_parse_pdl_func(pz_prv, py_results, query):
    py_results[0] = b'321'
    return 1

retval = dll.function_using_callback(py_parse_pdl_func)
print('retval =', retval)

Output:

results = '321'
retval = 1

Upvotes: 1

Related Questions