Passing a ctypes array of struct from Python to .dll

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.

This entry was posted in Hobbies, Programming, Technology. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s