Python ctypes module is very convenient for python to integrate C module.
Win7 X64 examples:
1) Call c dll library passing in arguments and return structure ptr
C lib:
-----------------------------------------------------------------------------------------
return_structure_ptr.h
#ifndef __RETURN_STRUCTURE_PTR_H__
#define __RETURN_STRUCTURE_PTR_H__
struct Dummy
{
int a;
double d;
char str[64];
};
#define DLLEXPORT __declspec(dllexport)
DLLEXPORT struct Dummy* return_structure_ptr(int a, int d, const char *str);
#endif /*__RETURN_STRUCTURE_PTR_H__*/
return_structure_ptr.c
#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include "return_structure_ptr.h"
DLLEXPORT struct Dummy* return_structure_ptr(int a, double d, const char *str)
{
struct Dummy* dummy = (struct Dummy*) malloc (sizeof(struct Dummy));
dummy->a = a;
dummy->d = d;
strcpy(dummy->str, str);
printf("%d, %f, %s\n", a, d, str);
return dummy;
}
DLLEXPORT void free_dummy_struture(struct Dummy* pd)
{
free(pd);
printf("0x%x\n", pd);
}
-------------------------------------------------------------------------------------------
Build the above c file to return_structure_ptr.dll. Note that the target architecture should be the same as Python's, say if Python is x64, the dll should be built for X64.
Otherwise, Python ctypes module will fail to load the dll.
VS tips:
VS2012 -> Project -> return_structure_ptr Properties -> Configuration Properties -> Linked -> Advanced -> Target Machine -> Pick "MachineX64"
VS2012 -> Build -> Configuration Manager -> Active Solution Platform -> New -> x64, also change the return_structure_ptr project in the following grid to x64 in the "Platform" column.
--------------------------------------------------------------------------------------------
Python code which load the dll:
from ctypes import *
class Dummy(Structure):
_fields_ = [('a', c_int), ('d', c_double), ('str', c_byte * 64)]
if __name__ == '__main__':
dll_handle = CDLL('return_structure_ptr.dll')
dll_handle.return_structure_ptr.restypes = POINTER(Dummy)
dll_handle.return_structure_ptr.argtypes = [c_int, c_double, c_char_p]
res_ptr = dll_handle.return_structure_ptr(c_int(10), c_double(40.123), c_char_p(b'hello'))
res_ptr = cast(res_ptr, POINTER(Dummy))
print(res_ptr.contents.a)
print(res_ptr.contents.d)
print(''.join(map(chr, res_ptr.contents.str)))
dll_handle.free_dummy_struture(res_ptr)
2) Passing in structure ptr as argument to C from Python and return the structure from C
C code:
head file:
DLLEXPORT struct Dummy* passing_in_and_return_structure(struct Dummy* pd);
C source file:
DLLEXPORT struct Dummy* passing_in_and_return_structure(struct Dummy* pd)
{
printf("%d, %f, %s, 0x%x\n", pd->a, pd->d, pd->str, pd);
pd->a = 1234;
pd->d = 5678.0;
strcpy(pd->str, "changed");
return pd;
}
Python Code
---------------------------------------------------------------------------------------------
dummy = Dummy()
dummy.a = c_int(1)
dummy.d = c_double(2.0)
for i, c in enumerate('xxx'):
dummy.str[i] = ord(c)
dll_handle.passing_in_and_return_structure(byref(dummy))
print(dummy.a, dummy.d, ''.join(map(chr, dummy.str)))
3) Passing in array as argument to C from python and return the array from C
C code:
head file:
DLLEXPORT int* passing_in_and_return_array(int *arr, int siz);
Source file:
DLLEXPORT int* passing_in_and_return_array(int *arr, int siz)
{
int i = 0;
for (; i < siz; i++)
{
printf("%d ", arr[i]);
arr[i] = i + 10;
}
printf("\n");
return arr;
}
Python code:
--------------------------------------------------------------------------------------------
INT_ARR = c_int * 10
a = INT_ARR()
for i in range(10):
a[i-1] = i
b = dll_handle.passing_in_and_return_array(a, len(a))
b = cast(b, POINTER(INT_ARR))
for i in range(10):
print(b.contents[i], end=' ')