I'm new to both ctypes and C and having trouble passing a struct pointer variable into a c-function called in python via ctypes. Please bear with me if it is too basic and obvious. Below is how my c-code looks like.
#include "mylib.h" (inside this mylib.h file MYSTRUCT is defined)
struct MYSTRUCT* modifystruct(a,b,c,d,e)
{
MYSTRUCT *mystpointer;
.....
.....
return mystpointer;
}
int mycfunction(mystpointer)
MYSTRUCT *mystpointer;
{
.........
.........
.........
}
Like above, modifystruct function update *mystpointer which is a pointer to MYSTRUCT and returns it. And mycfunction is to pass the returned mystpointer. In C, this works fine inside main function. But when I try to load the ".so" file using ctypes into python, it fails and I think I'm not correctly defining the argtype for mystpointer. Below is the brief python code I wrote. Let's say the above c-code is compiled to "mycmodule.so".
mylib=cdll.LoadLibrary("mycmodule.so")
mycfunction=mylib.mycfunction
mycfunction.restype=c_int
mycfunction.argtypes=[c_void_p]
mystpointer=c_void_p()
In the C code, I have to define mystpointer type as "MYSTRUCT *mystpointer;" However, I do not know how to do so in ctypes... instead, I defined the types as c_void_p but this triggers the failure. Thanks in advance!
I think what you may be missing is knowing exactly where you want the struct memory to be allocated. The c code below provides a function that allocates memory for the struct and returns a pointer to it (new_struct()).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int a;
int b;
} my_struct;
my_struct *new_struct()
{
my_struct *struct_instance = (my_struct *)malloc(sizeof(my_struct));
memset(struct_instance, 0, sizeof(my_struct));
return struct_instance;
}
int modify_struct(my_struct *ms) {
ms->a = 1;
ms->b = 2;
return 0;
}
void print_struct_c(my_struct *ms) {
printf("my_struct {\n"
" a = %d\n"
" b = %d\n"
"}\n", ms->a, ms->b);
}
From Python, to get the pointer, call the C function that does the allocation, then you can pass that to the other C functions that take it as a parameter.
import ctypes
lib_file_path = <<< path to lib file >>>
# Very simple example of how to declare a ctypes structure to twin the
# C library's declaration. This doesn't need to be declared if the Python
# code isn't going to need access to the struct's data members.
class MyStruct(ctypes.Structure):
_fields_ = [('a', ctypes.c_int),
('b', ctypes.c_int)]
def print_struct(s):
# Print struct that was allocated via Python ctypes.
print("my_struct.a = %d, my_struct.b = %d" % (s.a, s.b))
def print_struct_ptr(sptr):
# Print pointer to struct. Note the data members of the pointer are
# accessed via 'contents'.
print("my_struct_ptr.contents.a = %d, my_struct_ptr.contents.b = %d"
% (sptr.contents.a, sptr.contents.b))
my_c_lib = ctypes.cdll.LoadLibrary(lib_file_path)
# If you don't need to access the struct's data members from Python, then
# it's not necessary to declare MyStruct above. Also, in that case,
# 'restype' and 'argtypes' (below) can be set to ctypes.c_void_p instead.
my_c_lib.new_struct.restype = ctypes.POINTER(MyStruct)
my_c_lib.modify_struct.argtypes = [ctypes.POINTER(MyStruct)]
# Call C function to create struct instance.
my_struct_c_ptr = my_c_lib.new_struct()
print_struct_ptr(my_struct_c_ptr)
my_c_lib.modify_struct(my_struct_c_ptr)
print_struct_ptr(my_struct_c_ptr)
# Allocating struct instance from Python, then passing to C function.
my_struct_py = MyStruct(0, 0)
print_struct(my_struct_py)
my_c_lib.modify_struct(ctypes.byref(my_struct_py))
print_struct(my_struct_py)
# Data members of Python allocated struct can be acessed directly.
my_struct_py.a = 555
my_c_lib.print_struct_c(ctypes.byref(my_struct_py)) # Note use of 'byref()'
# to invoke c function.
The code above has been updated to include an example of how to allocate a struct instance via Python, and how to access the data members of either the C allocated or Python allocated struct (note differences in the print functions).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.