Home > Software design >  Declare NULL void pointer locally and pass it to API in ctypes
Declare NULL void pointer locally and pass it to API in ctypes

Time:10-10

I want to pass null void pointer to an API in ctypes. Below is my scenario,

C Code

//local variables
void *out_data = NULL;
uint32_t out_size;
StructureData pdata;

//API
Analyze(&pdata, &out_data, &out_size);

In Ctypes, how to pass local variables declared in C?

Python

api_call = dll.Analyze
api_call.argtypes = [ctypes.POINTER(pdata), ??, ??]
api_call.restypes = ctypes.c_int

pdata_obj = pdata() # casted datatypes for structure
Analyze(pdata_obj, ??, ??)

Actually what i'm trying is, In C *out_data pointer and out_size are declared locally and passing those into Analyze API. So likewise how we can declare in python and pass it to Analyze wrapper API.

CodePudding user response:

I made the following demo based on the C description of parameters:

test.c

#include <stdlib.h>
#include <stdint.h>

#ifdef _WIN32
#   define API __declspec(dllexport)
#else
#   define API
#endif

// Not defined by OP, so made something up for demonstration.
typedef struct StructureData {
    uint32_t number;
    uint32_t size;
} StructureData;

// implied parameters from OP description
API void Analyze(StructureData* pdata, void** out_data, uint32_t* out_size) {
    // something for demonstration
    *out_data = calloc(pdata->number, pdata->size);
    *out_size = pdata->number * pdata->size;
}

test.py

import ctypes as ct

class StructureData(ct.Structure):
    _fields_ = (('number', ct.c_uint32),
                ('size', ct.c_uint32))

dll = ct.CDLL('./test')
dll.Analyze.argtypes = (ct.POINTER(StructureData), # C StructureData*
 ct.POINTER(ct.c_void_p),  # C void**
 ct.POINTER(ct.c_uint32))  # C uint32_t*
dll.Analyze.restype = None # C void return

data = StructureData(5, 4) # StructureData instance, number=5, size=4
out_data = ct.c_void_p()   # C void* instance, null by default
out_size = ct.c_uint32()   # C uint32_t instance, 0 by default
print(out_data, out_size)

# ct.byref() is equivalent to & (address of) in C
dll.Analyze(ct.byref(data), ct.byref(out_data), ct.byref(out_size))
print(out_data, out_size)

# To see the data, cast to a C BYTE type and slice to output size
out = ct.cast(out_data, ct.POINTER(ct.c_ubyte))
print(out[:out_size.value])

Output:

c_void_p(None) c_ulong(0)
c_void_p(3049559977216) c_ulong(20)
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  • Related