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),
...)