1

I am calling a Python function with a set of parameters, as an example.

VOID CallPythonFunction(
      PSOME_COMPLEX_STRUCT Parameter1
    , PSOME_COMPLEX_STRUCT Parameter2
    , PSOME_COMPLEX_STRUCT Parameter3
    , PSOME_COMPLEX_STRUCT Parameter4
    )
{
    PyObject* module_name = PyString_FromString((char*)"plugin");
    PyObject* plugin = PyImport_Import(module_name);
    PyObject* PyTargetFunction = PyObject_GetAttrString(plugin, (char*)"some_function");
    PyObject* args = PyTuple_Pack(4
        , PyLong_FromUnsignedLong((ULONG) Paramater1)
        , PyLong_FromUnsignedLong((ULONG) Paramater2)
        , PyLong_FromUnsignedLong((ULONG) Paramater3)
        , PyLong_FromUnsignedLong((ULONG) Paramater4)
        );
    PyObject* result = PyObject_CallObject(PyTargetFunction, args);
}

This parameters ain't standard C types but pointers to complex structs instead, for example.

typedef struct _SOME_COMPLEX_STRUCT 
{
    int field1;
    char field2;
    int  whatever;
} SOME_COMPLEX_STRUCT, *PSOME_COMPLEX_STRUCT;

Since I converted it to python int objects I am not sure of how to handle this with ctypes or if I should create a Python object instead.

def some_function(parameter1, parameter2, parameter3, parameter4):
    pass

There is any "better"/canonical way to pass this structs as parameters?

How can I modify the data from Python module? I am using ctypes.

I've read this related questions/answers:

Passing a C struct to a Python function

passing c++ double pointer to python

Passing c struct to a function using ctypes

Community
  • 1
  • 1
Shaddy
  • 153
  • 1
  • 8
  • I'm figuring out that the key is use the `ctypes.cast` by creating the complex struct first in ctypes style. `ctypes.cast(parameter1, ctypes.POINTER(SOME_COMPLEX_STRUCT))` I'll test it tomorrow. – Shaddy Feb 11 '16 at 23:15
  • You shouldn't pass pointers as `long` values. On 64-bit Windows a `long` is 32-bit, so that will truncate the value. Use `PyLong_FromVoidPtr`. – Eryk Sun Feb 12 '16 at 06:01
  • To access this with ctypes, use `parameter1_view = SOME_COMPLEX_STRUCT.from_address(parameter1)`. It doesn't own the buffer that `parameter1` points at, so you may want to follow that with `parameter1 = SOME_COMPLEX_STRUCT.from_buffer_copy(parameter1_view)` to make a private copy. – Eryk Sun Feb 12 '16 at 06:01
  • In this case some of the parameters ar in/out buffers so the client may modify de content. I'm gonna try your suggestions and write back the final resolution. Thanks! – Shaddy Feb 12 '16 at 10:17
  • Finally got it by using the cast way. One question @eryksun, in terms of performance, is it better to use `STRUCTURE.from_address` than `ctypes.cast`? – Shaddy Feb 12 '16 at 23:24
  • 1
    `from_address` is more efficient. It just has to create an instance of the type and set its `b_ptr` to the address. `cast` is implemented using an FFI function call, which requires much more work. – Eryk Sun Feb 12 '16 at 23:38
  • Did you solve your problem yet ? – tauseef_CuriousGuy Sep 03 '17 at 22:00

0 Answers0