Calling a function from a dll

I have a dll which has been created in Visual C++. I am calling functions from the dll in Python.

Simple function that require a double do work fine.

A certain function however requires a pointer to a variable-size FP structure. In the documentation the Floating Point structure is defined as:

typedef struct _FP
{
unsigned short int rows;
unsigned short int cols;
double array[1];
} FP;

The array will actually have a size of rows times cols. Array consists of IEEE 8-byte floats

I fail to call the function defined in the dll. How would you call the function?

When posting code in Discourse (and other sites), it’s much easier to read if you format it:

```c
typedef struct _FP
{
  unsigned short int rows;
  unsigned short int cols;
  double array[1];
} FP;
```

In answer to your question, check out ctypes for Python’s interaction with C in shared libraries.

Define the FP struct and pass an instance by reference via ctypes.byref(instance). The FP record can be implemented in various ways. Since ctypes arrays are bounds checked, I prefer to use a property to handle a case like FP.array. For example:

class FP(ctypes.Structure):
    _fields_ = (('rows', ctypes.c_ushort),
                ('cols', ctypes.c_ushort),
                ('_array', ctypes.c_double * 1))

    def __init__(
        self, rows, cols, array=None, *,
        USHRT_MAX=((1 << (ctypes.sizeof(ctypes.c_ushort) * 8)) - 1),
    ):
        # ctypes.c_ushort requires int type
        self.rows = rows
        self.cols = cols
        if rows < 1 or cols < 1 or rows > USHRT_MAX or cols > USHRT_MAX:
            raise ValueError('rows and cols must be greater than 0 and '
                             'less than {}'.format(USHRT_MAX + 1))
        length = rows * cols
        if length > 1:
            ctypes.resize(self, ctypes.sizeof(self) +
                ctypes.sizeof(ctypes.c_double) * (length - 1))

        if array is not None:
            self.array[:] = array


    @property
    def array(self):
        length = self.rows * self.cols
        offset = __class__._array.offset
        return (ctypes.c_double * length).from_buffer(self, offset)
>>> fp = FP(2, 2, range(4))
>>> fp.array[:]
[0.0, 1.0, 2.0, 3.0]
>>> fp.array[:] = range(4, 8)
>>> fp.array[:]
[4.0, 5.0, 6.0, 7.0]
3 Likes

Brilliant! It works as I would like it. Thanks for your support, I should have asked weeks ago :slight_smile: .
Very much appreciated!