Home > Enterprise >  How to pass C structure containing custom defined datatypes in python
How to pass C structure containing custom defined datatypes in python

Time:06-10

I'm am writing in python code first time. Wanted to call C shared library function from python, however problem is unable to pass structure containing custom data types.

mylib.c

#include <stdio.h>
  
typedef int             integer;
typedef char            character;

struct temp {
        integer         a;
        character       b;
};

void
do_something(
        struct temp     *abc)
{
        abc->a = 100;
        abc->b = 'M';
        return;
}

Compilation step

# gcc -fPIC -shared -o mylib.so mylib.c 

Please consider interger and character as some other user defined datatypes, though in above example they are typedef of primitive datatypes int and char, but in my situation they are not, there is 2 or 3 level of indirection for various situations like if machine is 32bit or 64bit, or if working on solaris, AIX, or Linux etc..

I have written one sample python program also which is working fine if I use ctypes.c_int and ctypes.c_char, but I want to use integer and character custom datatypes inside python code. Basically wanted to write python code as it does not depend on actual primitive types.

Python3 program

import ctypes 
        
class sample(ctypes.Structure):
    _fields_ = [
            ("a", ctypes.c_int),
            ("b", ctypes.c_char)]

s = sample()
    
do_something = ctypes.CDLL("/root/Documents/python/mylib.so").do_something
do_something.argtypes = [ctypes.POINTER(sample)]
    
do_something(s)
    
print(s.a)
print(s.b)

Output:

100
b'M'

Thank you!

Responding to @Mark Tolonen queries


Though I cannot paste actual code, but below code is quite similar to actual one, here struct is having field of pid_t (though it is currently integer type internally, but relying on this fact is not good I think), timeval structure, and filesize which can be changed based on OFFSET64 declaration.

I want struct info (allocated inside python code) to get filled from C library.

#include <unistd.h>
#include <sys/time.h>

typedef unsigned int            __filesize;
typedef unsigned long long      __filesize64;
typedef unsigned long           inode_t;
#ifndef OFFSET64
typedef __filesize              filesize;
#endif
#ifdef  OFFSET64
typedef __filesize64            filesize;
#endif

struct info {
        pid_t           pid;
        struct timeval  atime;
        filesize        sz;
        inode_t         i_number;
};

void
did_something(
        struct info *p_info)
{
        p_info->pid = getpid();
        gettimeofday(&p_info->atime, NULL);

        p_info->sz = 512;
        p_info->i_number = 2;

        return;
}

CodePudding user response:

I didn't go digging up the definitions of pid_t, timeval, or inode_t but since filesize definition was provided here's a way to define it:

OFFSET64 = True # or False

if OFFSET64:
    filesize = ctypes.c_ulonglong
else:
    filesize = ctypes.c_uint

Then use filesize in the class definition for the structure:

class info(ctypes.Structure):
    _fields_ = (...
                ('sz', filesize),
                ...)
  • Related