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

7
  • 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. Commented Feb 11, 2016 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. Commented Feb 12, 2016 at 6: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. Commented Feb 12, 2016 at 6: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! Commented Feb 12, 2016 at 10:17
  • 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. Commented Feb 12, 2016 at 23:38

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.