Vincent M.
Vincent M.

Reputation: 1

Dereferencing pointer to array of strings in Python ctypes

I have this function for communicating with an optical laser tuner from its C library

long EXPORT newp_usb_get_model_serial_keys (char** ppBuffer);

where "ppbuffer" is "a pointer to an array of null terminated characters, where the array index is the 'DeviceID' and each element contains the Model/Serial Number key" (from the library header file). The function creates the array mention in ppbuffer's description and returns a 0 for success, non-zero for failure.

I've defined the following function in Python 2.7.15 as one of several to communicate with the laser:

from ctypes import *

def get_key(self):
    buf = create_string_buffer('\000'*1024)
    pbuf = pointer(buf)
    nread = c_ulong()
    status = self.lib.newp_usb_get_model_serial_keys(pbuf)
    if status != 0:
        raise CommandError("error")
    else:
        # dereference pointer and store/return values in the array

The newp_usb_get_model_serial_keys function is successful, but I've been having trouble dereferencing the pbuf pointer. I've struggled to understand some methods such as using cast() (and I'm not sure if that's what's best to use anyway), and using pbuf.contents simply returns

<ctypes.c_char_Array_1025 object at 0x0000000013557AC8>

which seems very different from what I've seen on other people's questions on similar topics.

I've tried using POINTER() instead of pointer() but there doesn't seem to be a ctype for a pointer to a string array for the first argument of POINTER(). I feel like there might be a better way to do this? Or maybe I'm just missing something here with how to access the strings being stored?

Upvotes: 0

Views: 1894

Answers (1)

Mark Tolonen
Mark Tolonen

Reputation: 177600

It is unclear how the function returns the value, but from the name it might be returning a pointer to an internal static buffer with serial/model information, so this should work. Note I have set the .argtypes and .restype of the function for some type checking.

Test DLL:

#define EXPORT __declspec(dllexport)

long EXPORT newp_usb_get_model_serial_keys (char** ppBuffer)
{
    static char item[] = "hello, world!";
    *ppBuffer = item;
    return 1;
}

Python:

from ctypes import *

dll = CDLL('test')
dll.newp_usb_get_model_serial_keys.argtypes = [POINTER(c_char_p)]
dll.newp_usb_get_model_serial_keys.restype = c_long

p = c_char_p()
dll.newp_usb_get_model_serial_keys(byref(p))
print(p.value)

Output:

b'hello, world!'

Upvotes: 2

Related Questions