Just create a pointer, assign the data afterwards;

import ctypes

class EmxArray(ctypes.Structure):
    """ creates a struct to match emxArray_real_T """

    _fields_ = [('data', ctypes.POINTER(ctypes.c_double)),
                ('size', ctypes.POINTER(ctypes.c_int)),
                ('allocatedSize', ctypes.c_int),
                ('numDimensions', ctypes.c_int),
                ('canFreeData', ctypes.c_bool)]

data = (1.3, 3.5, 2.7, 4.1)
L = len(data)

e = EmxArray()
e.data = (ctypes.c_double * L)(*data)
e.size = (ctypes.c_int * 1)(L)
# et cetera
Answer from Roland Smith on Stack Overflow
🌐
Python
docs.python.org › 3 › library › ctypes.html
ctypes — A foreign function library for Python
Here is a simple example of a POINT structure, which contains two integers named x and y, and also shows how to initialize a structure in the constructor: >>> from ctypes import * >>> class POINT(Structure): ... _fields_ = [("x", c_int), ... ("y", c_int)] ...
Top answer
1 of 2
15

Just create a pointer, assign the data afterwards;

import ctypes

class EmxArray(ctypes.Structure):
    """ creates a struct to match emxArray_real_T """

    _fields_ = [('data', ctypes.POINTER(ctypes.c_double)),
                ('size', ctypes.POINTER(ctypes.c_int)),
                ('allocatedSize', ctypes.c_int),
                ('numDimensions', ctypes.c_int),
                ('canFreeData', ctypes.c_bool)]

data = (1.3, 3.5, 2.7, 4.1)
L = len(data)

e = EmxArray()
e.data = (ctypes.c_double * L)(*data)
e.size = (ctypes.c_int * 1)(L)
# et cetera
2 of 2
4

I'm not well-versed with the Python-C interface, so what I'm suggesting may be less than ideal. My guess is that likely the crash is because x->data is never initialized and the memory to which it is pointing isn't allocated.

An approach I have taken when interfacing to MATLAB Coder generated code from other languages in the presence of emxArray arguments is to hand-write a C interface function that provides a simpler API. This relieves the burden of needing to construct an emxArray in the other environment (Android Java in my particular case). If the generated function foo takes and returns a 2-D double array, then something like the following could work:

void foo(double *x, int *szx, double **y, int *szy);

This function would take a pointer to the input data and its size and provide a pointer to the output data and its size. The implementation would look something like:

void foo(double *x, int *szx, double **y, int *szy) 
{
  emxArray_real_T *pEmx;
  emxArray_real_T *pEmy;

  /* Create input emxArray assuming 2-dimensional input */
  pEmx = emxCreateWrapper_real_T(x, szx[0], szx[1]);

  /* Create output emxArray (assumes that the output is not */
  /* written before allocation occurs) assuming 2-D output  */
  pEmy = emxCreateWrapper_real_T(NULL, 0, 0);

  /* Call generated code (call foobar_initialize/terminate elsewhere) */
  foobar(pEmx, pEmy);

  /* Unpack result - You may want to MALLOC storage in *y and */
  /* MEMCPY there alternatively                               */
  *y = pEmy->data;
  szy[0] = pEmy->size[0];
  szy[1] = pEmy->size[1];

  /* Clean up any memory allocated in the emxArrays (e.g. the size vectors) */
  emxDestroyArray_real_T(pEmx);
  emxDestroyArray_real_T(pEmy);
}

You should be able to call this function from Python more simply and pass in the desired data as needed.

My other answer has more details on the emxArray_* functions found in the file foobar_emxAPI.h.

🌐
SageMath
doc.sagemath.org › html › en › thematic_tutorials › numerical_sage › ctypes_examples.html
More complicated ctypes example - Thematic Tutorials
Let’s discuss the above code. The original C code stored a sparse matrix as a linked list. The python code uses the ctypes Structure class to create structures mirroring the structs in the C code. To create python object representing a C struct, simply create class that derives from Structure.
🌐
CodersLegacy
coderslegacy.com › home › structs with python ctypes
Structs with Python Ctypes - CodersLegacy
October 30, 2022 - If you do not, then these will remain as local variables, and when you return these pointers to Python and the function ends, then the local memory will be destroyed, and your Python program will receive dangling pointers. We don’t want that, so we declare our memory dynamically which means that it exists until we explicitly free it. And we need to do this for both the Struct, and the string inside it. (Because both objects are not primary datatypes, and cannot be passed by value) import ctypes import os class Student(ctypes.Structure): _fields_ = [("name", ctypes.c_char_p)] path = os.getcwd() clibrary = ctypes.CDLL(os.path.join(path, 'clibrary.so'))
🌐
ProgramCreek
programcreek.com › python › example › 1122 › ctypes.Structure
Python Examples of ctypes.Structure
def __init__(self, **kwargs): """ Ctypes.Structure with integrated default values. https://stackoverflow.com/questions/7946519/default-values-in-a-ctypes-structure/25892189#25892189 :param kwargs: values different to defaults :type kwargs: dict """ # sanity checks defaults = type(self)._defaults_ assert type(defaults) is types.DictionaryType # use defaults, but override with keyword arguments, if any values = defaults.copy() for (key, val) in kwargs.items(): values[key] = val # appropriately initialize ctypes.Structure #super().__init__(**values) # Python 3 syntax return Structure.__init__(self, **values) # Python 2 syntax # http://stackoverflow.com/questions/1825715/how-to-pack-and-unpack-using-ctypes-structure-str/1827666#1827666 # https://wiki.python.org/moin/ctypes
🌐
Iotexpert
iotexpert.com › stupid-python-tricks-c-structures-using-the-ctypes-module-part-2
Stupid Python Tricks: C-Structures using the ctypes Module (part 2) – IoT Expert
class MyStruct1(ctypes.BigEndianStructure): _pack_ = 1 _fields_ = [ ("first",ctypes.c_uint8,4), ("second",ctypes.c_uint8,4), ("third",ctypes.c_uint8,8), ] def __new__(self,sb=None): if(sb): return self.from_buffer_copy(sb) else: return ctypes.BigEndianStructure.__new__(self) def __init__(self,sb=None): pass print("Next case") c = MyStruct1() c.first = 0xa c.second = 0xb c.third = 0xcd print(bytes(c)) d = MyStruct1(b'\xab\xcd') print(bytes(d)) Now when I run it, things are good. (venv) $ python ex-struct.py Next case b'\xab\xcd' b'\xab\xcd'
🌐
Python.org
discuss.python.org › python help
ctypes.Structure and bitfields - Python Help - Discussions on Python.org
March 20, 2023 - I have been using bit-fields with ctypes.Structure. I have a bitfield struct, and my issue is that no matter what I do, I am unable to set the values for my fields. A structure with the following definition: from ctypes import Structure, c_byte, c_int class Demo (Structure): _fields_ = [ ('f1', c_byte, 8), ('f2', c_int, 21), ('f3', c_byte, 2), ('f4', c_byte, 1) ] I have set the above struct using from_buffer_copy with a value of b'\x01\x0f\x00\xe0' (Binary representation of C struc...
🌐
Samuelstevens
samuelstevens.me › writing › optimizing-python-code-with-ctypes
Optimizing Python Code with ctypes
All structs are classes that inherit from ctypes.Structure. The only field is _fields_, which is a list of tuples. Each tuple is (<variable-name>, <ctypes.TYPE>). ctypes has types like c_char (char), and c_char_p (*char). ctypes also includes POINTER() which creates a pointer type from any ...
Find elsewhere
🌐
Medium
medium.com › @datasciencefilmmaker › my-god-its-full-of-stars-2-d75d01d2cb94
My God, It’s Full of Stars (2/7) — Accessing C Structures in Python Using Ctypes | by Data Science Filmmaker | Medium
January 18, 2024 - It makes extensive use of structures and pointers to make accessing memory more efficient than the equivalent object-oriented version, and way more efficient than the Python equivalent would be. I wanted to take advantage of the speed of C while still using mostly Python syntax. Enter the “ctypes” library.
🌐
dbader.org
dbader.org › blog › python-ctypes-tutorial-part-2
Interfacing Python and C: Advanced “ctypes” Features – dbader.org
November 7, 2017 - Learn advanced patterns for interfacing Python with native libraries, like dealing with C structs from Python and pass-by-value versus pass-by-reference semantics. The built-in ctypes module is a powerful feature in Python, allowing you to use existing libraries in other languages by writting ...
🌐
Stanford
sporadic.stanford.edu › thematic_tutorials › numerical_sage › ctypes_examples.html
More complicated ctypes example — Thematic Tutorials v9.3.beta9
Let’s discuss the above code. The original C code stored a sparse matrix as a linked list. The python code uses the ctypes Structure class to create structures mirroring the structs in the C code. To create python object representing a C struct, simply create class that derives from Structure.
🌐
YouTube
youtube.com › coderslegacy
Using Structs and Classes with Python Ctypes - YouTube
In this Video, we will explore how to create, pass and return Structs between our C and Python program using the ctypes library. C File Compilation Code:gcc ...
Published: November 18, 2022
Views: 5K
🌐
Pendancer
python.pendancer.com › advanced › ctypes.html
CTypes and Structures - Python
For instance, let's assume a function within a DLL requires a pointer to a struct to be passed. A real world example of this would be a DLL file that communicates with hardware. Below is an example of how to create a C struct using Python ctypes
🌐
University of Chicago
people.cs.uchicago.edu › ~amr › 122 › labs › cstructs.html
CMSC 12200 - Structs in C and bridging with Python using CTypes - Februrary 2, 2011
CTypes allows us to pull compiled C functions from libraries and use them directly in Python. From the terminal inspect the folder ctypesexample in the lab-cstructs folder you downloaded. This contains a file, test.c, which contains the standard fibonacci function written in C.
🌐
Nullteilerfrei
blag.nullteilerfrei.de › 2021 › 06 › 20 › prettier-struct-definitions-for-python-ctypes
Prettier Struct Definitions for Python CTypes – nullteilerfrei
June 20, 2021 - Now, the [ctypes][] [struct definitions][structs] are a little annoying because they do not give you type hints. You can add the type hints _on top_ of the `_fields_` attribute but that looks a little silly because you _literally_ [write everything twice][wet]. In Python 3.7+ ((Starting in Python 3.7, dictionaries keep the insertion order.)), you can solve this using a metaclass, and one stigma of metaclasses is that they have very few applications, so I decided to blog about this one: ```python class FieldsFromTypeHints(type(ctypes.Structure)): def __new__(cls, name, bases, namespace): from t
🌐
GitHub
github.com › nixawk › hello-python3 › blob › master › ctypes › ctypes.Structure.py
hello-python3/ctypes/ctypes.Structure.py at master · nixawk/hello-python3
#!/usr/bin/python · # -*- coding: utf-8 -*- · from ctypes import * · · """ class ctypes.Structure(*args, **kw) · Abstract base class for structures in native byte order.
Author: nixawk
Top answer
1 of 3
38

Here's a working example. It looks like you are passing the wrong type to the function and the structure was declared incorrectly for the Data member. Note below how to declare the type of a fixed-size array when declaring the Python structure.

test.c ("cl /W4 /LD .c" on Windows):

#include <stdio.h>

#ifdef _WIN32
#   define SMBUS_API __declspec(dllexport)
#else
#   define SMBUS_API
#endif

#define SMB_MAX_DATA_SIZE 5

typedef void* SMBUS_HANDLE;

typedef struct _SMB_REQUEST {
    unsigned char Address;
    unsigned char Command;
    unsigned char BlockLength;
    unsigned char Data[SMB_MAX_DATA_SIZE];
} SMB_REQUEST;

SMBUS_API int SmBusReadByte(SMBUS_HANDLE handle, SMB_REQUEST *request) {
    for(unsigned char i = 0; i < request->BlockLength; ++i)
        request->Data[i] = i;
    return request->BlockLength;
}

SMBUS_API SMBUS_HANDLE OpenSmbus(void) {
    return (void*)0x12345678;
}

test.py:

import ctypes as ct

SMB_MAX_DATA_SIZE = 5
ARRAY = ct.c_ubyte * SMB_MAX_DATA_SIZE

class SMB_REQUEST(ct.Structure):
    _fields_ = (('Address', ct.c_ubyte),
                ('Command', ct.c_ubyte),
                ('BlockLength', ct.c_ubyte),
                ('Data', ARRAY))

dll = ct.CDLL('./test')
smbus_read_byte = dll.SmBusReadByte
smbus_read_byte.argtypes = ct.c_void_p, ct.POINTER(SMB_REQUEST)
smbus_read_byte.restype = ct.c_int
open_smbus = dll.OpenSmbus
open_smbus.argtypes = ()
open_smbus.restype = ct.c_void_p

handle = open_smbus()
print(f'{handle = :08X}h')

smb_request = SMB_REQUEST(1, 2, 5)

print(f'returned = {smbus_read_byte(handle, smb_request)}')
print(f'Address = {smb_request.Address}')
print(f'Command = {smb_request.Command}')
print(f'BlockLength = {smb_request.BlockLength}')
for i, b in enumerate(smb_request.Data):
    print(f'Data[{i}] = {b:02X}h')

Output:

handle = 12345678h
returned = 5
Address = 1
Command = 2
BlockLength = 5
Data[0] = 00h
Data[1] = 01h
Data[2] = 02h
Data[3] = 03h
Data[4] = 04h
2 of 3
7

You're almost there. You should use c_char * SMB_MAX_DATA_SIZE as the type for the definition of Data. This works for me on Mac OS X:

Shared library:

$ cat test.c
#include <stdio.h>

#define SMB_MAX_DATA_SIZE 16

typedef struct _SMB_REQUEST
{
  unsigned char Address;
  unsigned char Command;
  unsigned char BlockLength;
  unsigned char Data[SMB_MAX_DATA_SIZE];
} SMB_REQUEST;

int SmBusReadByte(void *handle, SMB_REQUEST *request)
{
  printf("SmBusReadByte: handle=%p request=[%d %d %d %s]\n", handle, 
      request->Address, request->Command, request->BlockLength, request->Data);
  return 13;
}

$ gcc test.c -fPIC -shared -o libtest.dylib

Python driver:

$ cat test.py
import ctypes

SMB_MAX_DATA_SIZE = 16

class SMB_REQUEST(ctypes.Structure):
    _fields_ = [("Address", ctypes.c_ubyte),
                ("Command", ctypes.c_ubyte),
                ("BlockLength", ctypes.c_ubyte),
                ("Data", ctypes.c_char * SMB_MAX_DATA_SIZE)]

libtest = ctypes.cdll.LoadLibrary('libtest.dylib')

req = SMB_REQUEST(1, 2, 3, 'test')

result = libtest.SmBusReadByte(ctypes.c_voidp(0x12345678), ctypes.byref(req))

print 'result: %d' % result

$ python test.py
SmBusReadByte: handle=0x12345678 request=[1 2 3 test]
result: 13

UPDATE

You're having problems because you need to set the result type of open_smbus to void*. By default, ctypes assumes that functions return ints. You need to say this:

open_smbus.restype = ctypes.c_void_p

You were getting an error because you were using c_void_p() (note the extra parentheses). There's an important distinction between c_void_p and c_void_p(). The former is a type, and the latter is an instance of a type. c_void_p represents the C type void*, whereas c_void_p() represents an actual pointer instance (with a default value of 0).

🌐
Ifnamemain
ifnamemain.com › posts › 2013 › Dec › 10 › c_structs_python
C Structs and Python - ifnamemain
To declare the struct in Python requires the creation of new class based on the ctypes.Structure object :
🌐
Wumb0
wumb0.in › a-better-way-to-work-with-raw-data-types-in-python.html
A Better Way to Work with Raw Data Types in Python - wumb0in'
March 11, 2017 - from ctypes import * class MyFirstStructure(BigEndianStructure): _pack_ = 1 _fields_ = [ ('intfield', c_int), ('bytefield', c_ubyte)] This is a 5 byte structure equivalent to the following C code: