I’m working on a small project that requires interfacing Python to a C .dll. I’ve never had to pass an array of structures by reference before with ctypes, so here’s a quick sanity check I did to make sure I was doing it right before diving into something heavier.
The .dll source:
// structtest.cpp : Defines the exported functions for the DLL application. // #include "stdafx.h" #ifdef STRUCTTEST_EXPORTS #define STRUCTTEST_API __declspec(dllexport) #else #define STRUCTTEST_API __declspec(dllimport) #endif extern "C" { struct structtest { char x; int y; long z; }; STRUCTTEST_API void fillonestruct(struct structtest *t) { t->x = 'A'; t->y = 1234; t->z = 5678; } STRUCTTEST_API void fillmultiplestruct(struct structtest *t, int n) { for (int i = 0; i < n; i++) { t->x = (char)((int)'A' + i); t->y = i; t->z = i; t++; } } }
Here’s the Python program that uses the .dll:
from ctypes import * class structtest(Structure): _fields_ = [("x", c_char), ("y", c_int), ("z", c_long)] if __name__ == "__main__": n_struct2 = 5 lib = CDLL("structtest.dll") struct1 = structtest() struct2 = (structtest * n_struct2)() print("Before passing to .dll") print("Struct1 x:{} y:{} z:{}".format(struct1.x, struct1.y, struct1.z)) for i in range(n_struct2): print("Struct2[{}] x:{} y:{} z:{}".format(i, struct2[i].x, struct2[i].y, struct2[i].z)) lib.fillonestruct(byref(struct1)) lib.fillmultiplestruct(byref(struct2), c_int(n_struct2)) print("\nAfter passing to .dll") print("Struct1 x:{} y:{} z:{}".format(struct1.x, struct1.y, struct1.z)) for i in range(n_struct2): print("Struct2[{}] x:{} y:{} z:{}".format(i, struct2[i].x, struct2[i].y, struct2[i].z))
The output:
Before passing to .dll
Struct1 x: y:0 z:0
Struct2[0] x: y:0 z:0
Struct2[1] x: y:0 z:0
Struct2[2] x: y:0 z:0
Struct2[3] x: y:0 z:0
Struct2[4] x: y:0 z:0
After passing to .dll
Struct1 x:A y:1234 z:5678
Struct2[0] x:A y:0 z:0
Struct2[1] x:B y:1 z:1
Struct2[2] x:C y:2 z:2
Struct2[3] x:D y:3 z:3
Struct2[4] x:E y:4 z:4
So hooray – everything works as expected.