Skip to content

Instantly share code, notes, and snippets.

@pfalcon
Created February 3, 2014 14:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pfalcon/8785113 to your computer and use it in GitHub Desktop.
Save pfalcon/8785113 to your computer and use it in GitHub Desktop.
MicroPython - cstruct example
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "stream.h"
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
//int cstruct_find_field(const char *name, const char **arr, int size);
typedef int (*getter_fun_t)(void *p, int id);
typedef void (*setter_fun_t)(void *p, int id, int val);
void cstruct_load_attr(const char **fields, int num_fields, getter_fun_t get_field, mp_obj_t self_in, qstr attr, mp_obj_t *dest);
bool cstruct_store_attr(const char **fields, int num_fields, setter_fun_t set_field, mp_obj_t self_in, qstr attr, mp_obj_t value);
void cstruct_print(const char **fields, int num_fields, getter_fun_t get_field,
void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind);
typedef struct _mp_obj_sockaddr_in_t {
mp_obj_base_t base;
struct sockaddr_in cstruct;
} mp_obj_sockaddr_in_t;
enum {
ID_sin_family,
ID_sin_addr,
ID_sin_port,
};
static const char *sockaddr_in_fields[] = { "sin_family", "sin_addr", "sin_port" };
static int sockaddr_in_get_field(void *_s, int id) {
struct sockaddr_in *s = _s;
switch (id) {
case ID_sin_family:
return s->sin_family; break;
case ID_sin_addr:
return *(uint32_t*)&s->sin_addr; break;
case ID_sin_port:
return s->sin_port; break;
}
return -1;
}
static void sockaddr_in_set_field(void *_s, int id, int val) {
struct sockaddr_in *s = _s;
switch (id) {
case ID_sin_family:
s->sin_family = val; break;
case ID_sin_addr:
*(uint32_t*)&s->sin_addr = val; break;
case ID_sin_port:
s->sin_port = val; break;
}
}
static void sockaddr_in_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
cstruct_load_attr(sockaddr_in_fields, ARRAY_SIZE(sockaddr_in_fields), sockaddr_in_get_field, self_in, attr, dest);
}
static bool sockaddr_in_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
return cstruct_store_attr(sockaddr_in_fields, ARRAY_SIZE(sockaddr_in_fields), sockaddr_in_set_field, self_in, attr, value);
}
extern const mp_obj_type_t sockaddr_in_type;
static mp_obj_t sockaddr_in_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
mp_obj_sockaddr_in_t *o = m_new(mp_obj_sockaddr_in_t, 1);
o->base.type = &sockaddr_in_type;
memset(&o->cstruct, 0, sizeof(o->cstruct));
return (mp_obj_t)o;
}
static void sockaddr_in_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
cstruct_print(sockaddr_in_fields, ARRAY_SIZE(sockaddr_in_fields), sockaddr_in_get_field, print, env, o_in, kind);
}
static machine_int_t sockaddr_in_get_buffer(mp_obj_t o_in, buffer_info_t *bufinfo, int flags) {
mp_obj_sockaddr_in_t *o = o_in;
bufinfo->buf = &o->cstruct;
bufinfo->len = sizeof(o->cstruct);
return 0;
}
const mp_obj_type_t sockaddr_in_type = {
{ &mp_const_type },
"sockaddr_in",
.print = sockaddr_in_print,
.make_new = sockaddr_in_make_new,
.load_attr = sockaddr_in_load_attr,
.store_attr = sockaddr_in_store_attr,
.buffer_p = { .get_buffer = sockaddr_in_get_buffer },
};
//-------------------
#include <string.h>
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
typedef int (*getter_fun_t)(void *p, int id);
typedef void (*setter_fun_t)(void *p, int id, int val);
static int cstruct_find_field(const char *name, const char **arr, int size) {
for (int i = 0; i < size; i++) {
if (!strcmp(arr[i], name)) {
return i;
}
}
return -1;
}
void cstruct_load_attr(const char **fields, int num_fields, getter_fun_t get_field, mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
struct _mp_obj_base_t *self = self_in;
int id = cstruct_find_field(qstr_str(attr), fields, num_fields);
if (id < 0) {
return;
}
// Pass pointer to beyond _mp_obj_base_t, i.e. to cstruct
machine_int_t v = get_field(self + 1, id);
dest[1] = mp_obj_new_int(v);
}
bool cstruct_store_attr(const char **fields, int num_fields, setter_fun_t set_field, mp_obj_t self_in, qstr attr, mp_obj_t value) {
struct _mp_obj_base_t *self = self_in;
int id = cstruct_find_field(qstr_str(attr), fields, num_fields);
if (id < 0) {
return false;
}
machine_int_t v = mp_obj_get_int(value);
// Pass pointer to beyond _mp_obj_base_t, i.e. to cstruct
set_field(self + 1, id, v);
return true;
}
void cstruct_print(const char **fields, int num_fields, getter_fun_t get_field,
void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
struct _mp_obj_base_t *o = o_in;
print(env, o->type->name);
print(env, "(");
for (int i = 0; i < num_fields; i++) {
if (i > 0) {
print(env, ", ");
}
print(env, "%s=0x%x", fields[i], get_field(o + 1, i));
}
print(env, ")");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment