You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2391 lines
64 KiB
C
2391 lines
64 KiB
C
/***********************************************************************************************
|
|
************************************************************************************************
|
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
!!!!!!!! Warning this file was generated from a set of *.nobj.lua definition files !!!!!!!!!!!!!
|
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
************************************************************************************************
|
|
***********************************************************************************************/
|
|
|
|
#include "lua.h"
|
|
#include "lauxlib.h"
|
|
#include "lualib.h"
|
|
|
|
#include <string.h>
|
|
#include "zmq.h"
|
|
|
|
|
|
#define REG_PACKAGE_IS_CONSTRUCTOR 0
|
|
#define REG_OBJECTS_AS_GLOBALS 0
|
|
#define OBJ_DATA_HIDDEN_METATABLE 1
|
|
#define LUAJIT_FFI 1
|
|
#define USE_FIELD_GET_SET_METHODS 0
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
/* define some types that we need. */
|
|
typedef __int32 int32_t;
|
|
typedef unsigned __int32 uint32_t;
|
|
|
|
#define FUNC_UNUSED
|
|
|
|
#else
|
|
|
|
#include <stdint.h>
|
|
|
|
#define FUNC_UNUSED __attribute__((unused))
|
|
|
|
#endif
|
|
|
|
#if defined(__GNUC__) && (__GNUC__ >= 4)
|
|
#define assert_obj_type(type, obj) \
|
|
assert(__builtin_types_compatible_p(typeof(obj), type *))
|
|
#else
|
|
#define assert_obj_type(type, obj)
|
|
#endif
|
|
|
|
#ifndef obj_type_free
|
|
#define obj_type_free(type, obj) do { \
|
|
assert_obj_type(type, obj); \
|
|
free((obj)); \
|
|
} while(0)
|
|
#endif
|
|
|
|
#ifndef obj_type_new
|
|
#define obj_type_new(type, obj) do { \
|
|
assert_obj_type(type, obj); \
|
|
(obj) = malloc(sizeof(type)); \
|
|
} while(0)
|
|
#endif
|
|
|
|
typedef struct obj_type obj_type;
|
|
|
|
typedef void (*base_caster_t)(void **obj);
|
|
|
|
typedef void (*dyn_caster_t)(void **obj, obj_type **type);
|
|
|
|
#define OBJ_TYPE_FLAG_WEAK_REF (1<<0)
|
|
#define OBJ_TYPE_SIMPLE (1<<1)
|
|
struct obj_type {
|
|
dyn_caster_t dcaster; /**< caster to support casting to sub-objects. */
|
|
int32_t id; /**< type's id. */
|
|
uint32_t flags; /**< type's flags (weak refs) */
|
|
const char *name; /**< type's object name. */
|
|
};
|
|
|
|
typedef struct obj_base {
|
|
int32_t id;
|
|
base_caster_t bcaster;
|
|
} obj_base;
|
|
|
|
typedef enum obj_const_type {
|
|
CONST_UNKOWN = 0,
|
|
CONST_BOOLEAN = 1,
|
|
CONST_NUMBER = 2,
|
|
CONST_STRING = 3
|
|
} obj_const_type;
|
|
|
|
typedef struct obj_const {
|
|
const char *name; /**< constant's name. */
|
|
const char *str;
|
|
double num;
|
|
obj_const_type type;
|
|
} obj_const;
|
|
|
|
typedef enum obj_field_type {
|
|
TYPE_UNKOWN = 0,
|
|
TYPE_UINT8 = 1,
|
|
TYPE_UINT16 = 2,
|
|
TYPE_UINT32 = 3,
|
|
TYPE_UINT64 = 4,
|
|
TYPE_INT8 = 5,
|
|
TYPE_INT16 = 6,
|
|
TYPE_INT32 = 7,
|
|
TYPE_INT64 = 8,
|
|
TYPE_DOUBLE = 9,
|
|
TYPE_FLOAT = 10,
|
|
TYPE_STRING = 11
|
|
} obj_field_type;
|
|
|
|
typedef struct obj_field {
|
|
const char *name; /**< field's name. */
|
|
uint32_t offset; /**< offset to field's data. */
|
|
obj_field_type type; /**< field's data type. */
|
|
uint32_t flags; /**< is_writable:1bit */
|
|
} obj_field;
|
|
|
|
typedef struct reg_sub_module {
|
|
obj_type *type;
|
|
int is_package;
|
|
const luaL_reg *pub_funcs;
|
|
const luaL_reg *methods;
|
|
const luaL_reg *metas;
|
|
const obj_base *bases;
|
|
const obj_field *fields;
|
|
const obj_const *constants;
|
|
} reg_sub_module;
|
|
|
|
#define OBJ_UDATA_FLAG_OWN (1<<0)
|
|
#define OBJ_UDATA_FLAG_LOOKUP (1<<1)
|
|
#define OBJ_UDATA_LAST_FLAG (OBJ_UDATA_FLAG_LOOKUP)
|
|
typedef struct obj_udata {
|
|
void *obj;
|
|
uint32_t flags; /**< lua_own:1bit */
|
|
} obj_udata;
|
|
|
|
/* use static pointer as key to weak userdata table. */
|
|
static char *obj_udata_weak_ref_key = "obj_udata_weak_ref_key";
|
|
|
|
#if LUAJIT_FFI
|
|
typedef struct ffi_export_symbol {
|
|
const char *name;
|
|
void *sym;
|
|
} ffi_export_symbol;
|
|
#endif
|
|
|
|
|
|
#define obj_type_id_zmq_msg_t 0
|
|
#define obj_type_zmq_msg_t_check(L, _index) \
|
|
(zmq_msg_t *)obj_simple_udata_luacheck(L, _index, &(obj_type_zmq_msg_t))
|
|
#define obj_type_zmq_msg_t_delete(L, _index, flags) \
|
|
(zmq_msg_t *)obj_simple_udata_luadelete(L, _index, &(obj_type_zmq_msg_t), flags)
|
|
#define obj_type_zmq_msg_t_push(L, obj, flags) \
|
|
obj_simple_udata_luapush(L, obj, sizeof(zmq_msg_t), &(obj_type_zmq_msg_t))
|
|
|
|
#define obj_type_id_ZMQ_Socket 1
|
|
#define obj_type_ZMQ_Socket_check(L, _index) \
|
|
obj_udata_luacheck(L, _index, &(obj_type_ZMQ_Socket))
|
|
#define obj_type_ZMQ_Socket_delete(L, _index, flags) \
|
|
obj_udata_luadelete(L, _index, &(obj_type_ZMQ_Socket), flags)
|
|
#define obj_type_ZMQ_Socket_push(L, obj, flags) \
|
|
obj_udata_luapush_weak(L, (void *)obj, &(obj_type_ZMQ_Socket), flags)
|
|
|
|
#define obj_type_id_ZMQ_Ctx 2
|
|
#define obj_type_ZMQ_Ctx_check(L, _index) \
|
|
obj_udata_luacheck(L, _index, &(obj_type_ZMQ_Ctx))
|
|
#define obj_type_ZMQ_Ctx_delete(L, _index, flags) \
|
|
obj_udata_luadelete(L, _index, &(obj_type_ZMQ_Ctx), flags)
|
|
#define obj_type_ZMQ_Ctx_push(L, obj, flags) \
|
|
obj_udata_luapush_weak(L, (void *)obj, &(obj_type_ZMQ_Ctx), flags)
|
|
|
|
|
|
|
|
typedef int ZMQ_Error;
|
|
|
|
static void error_code__ZMQ_Error__push(lua_State *L, ZMQ_Error err);
|
|
|
|
|
|
static obj_type obj_type_zmq_msg_t = { NULL, 0, OBJ_TYPE_SIMPLE, "zmq_msg_t" };
|
|
static obj_type obj_type_ZMQ_Socket = { NULL, 1, OBJ_TYPE_FLAG_WEAK_REF, "ZMQ_Socket" };
|
|
static obj_type obj_type_ZMQ_Ctx = { NULL, 2, OBJ_TYPE_FLAG_WEAK_REF, "ZMQ_Ctx" };
|
|
|
|
|
|
#ifndef REG_PACKAGE_IS_CONSTRUCTOR
|
|
#define REG_PACKAGE_IS_CONSTRUCTOR 1
|
|
#endif
|
|
|
|
#ifndef REG_OBJECTS_AS_GLOBALS
|
|
#define REG_OBJECTS_AS_GLOBALS 0
|
|
#endif
|
|
|
|
#ifndef OBJ_DATA_HIDDEN_METATABLE
|
|
#define OBJ_DATA_HIDDEN_METATABLE 1
|
|
#endif
|
|
|
|
static FUNC_UNUSED obj_udata *obj_udata_toobj(lua_State *L, int _index) {
|
|
obj_udata *ud;
|
|
size_t len;
|
|
|
|
/* make sure it's a userdata value. */
|
|
ud = (obj_udata *)lua_touserdata(L, _index);
|
|
if(ud == NULL) {
|
|
luaL_typerror(L, _index, "userdata"); /* is not a userdata value. */
|
|
}
|
|
/* verify userdata size. */
|
|
len = lua_objlen(L, _index);
|
|
if(len != sizeof(obj_udata)) {
|
|
/* This shouldn't be possible */
|
|
luaL_error(L, "invalid userdata size: size=%d, expected=%d", len, sizeof(obj_udata));
|
|
}
|
|
return ud;
|
|
}
|
|
|
|
static FUNC_UNUSED int obj_udata_is_compatible(lua_State *L, obj_udata *ud, void **obj, base_caster_t *caster, obj_type *type) {
|
|
obj_base *base;
|
|
obj_type *ud_type;
|
|
lua_pushlightuserdata(L, type);
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */
|
|
if(lua_rawequal(L, -1, -2)) {
|
|
*obj = ud->obj;
|
|
/* same type no casting needed. */
|
|
return 1;
|
|
} else {
|
|
/* Different types see if we can cast to the required type. */
|
|
lua_rawgeti(L, -2, type->id);
|
|
base = lua_touserdata(L, -1);
|
|
lua_pop(L, 1); /* pop obj_base or nil */
|
|
if(base != NULL) {
|
|
*caster = base->bcaster;
|
|
/* get the obj_type for this userdata. */
|
|
lua_pushliteral(L, ".type");
|
|
lua_rawget(L, -3); /* type's metatable. */
|
|
ud_type = lua_touserdata(L, -1);
|
|
lua_pop(L, 1); /* pop obj_type or nil */
|
|
if(base == NULL) {
|
|
luaL_error(L, "bad userdata, missing type info.");
|
|
return 0;
|
|
}
|
|
/* check if userdata is a simple object. */
|
|
if(ud_type->flags & OBJ_TYPE_SIMPLE) {
|
|
*obj = ud;
|
|
} else {
|
|
*obj = ud->obj;
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static FUNC_UNUSED obj_udata *obj_udata_luacheck_internal(lua_State *L, int _index, void **obj, obj_type *type) {
|
|
obj_udata *ud;
|
|
base_caster_t caster = NULL;
|
|
/* make sure it's a userdata value. */
|
|
ud = (obj_udata *)lua_touserdata(L, _index);
|
|
if(ud != NULL) {
|
|
/* check object type by comparing metatables. */
|
|
if(lua_getmetatable(L, _index)) {
|
|
if(obj_udata_is_compatible(L, ud, obj, &(caster), type)) {
|
|
lua_pop(L, 2); /* pop both metatables. */
|
|
/* apply caster function if needed. */
|
|
if(caster != NULL && *obj != NULL) {
|
|
caster(obj);
|
|
}
|
|
/* check object pointer. */
|
|
if(*obj == NULL) {
|
|
luaL_error(L, "null %s", type->name); /* object was garbage collected? */
|
|
}
|
|
return ud;
|
|
}
|
|
}
|
|
}
|
|
luaL_typerror(L, _index, type->name); /* is not a userdata value. */
|
|
return NULL;
|
|
}
|
|
|
|
static FUNC_UNUSED void *obj_udata_luacheck(lua_State *L, int _index, obj_type *type) {
|
|
void *obj = NULL;
|
|
obj_udata_luacheck_internal(L, _index, &(obj), type);
|
|
return obj;
|
|
}
|
|
|
|
static FUNC_UNUSED void *obj_udata_luadelete(lua_State *L, int _index, obj_type *type, int *flags) {
|
|
void *obj;
|
|
obj_udata *ud = obj_udata_luacheck_internal(L, _index, &(obj), type);
|
|
*flags = ud->flags;
|
|
/* null userdata. */
|
|
ud->obj = NULL;
|
|
ud->flags = 0;
|
|
/* clear the metatable to invalidate userdata. */
|
|
lua_pushnil(L);
|
|
lua_setmetatable(L, _index);
|
|
return obj;
|
|
}
|
|
|
|
static FUNC_UNUSED void obj_udata_luapush(lua_State *L, void *obj, obj_type *type, int flags) {
|
|
obj_udata *ud;
|
|
/* convert NULL's into Lua nil's. */
|
|
if(obj == NULL) {
|
|
lua_pushnil(L);
|
|
return;
|
|
}
|
|
/* check for type caster. */
|
|
if(type->dcaster) {
|
|
(type->dcaster)(&obj, &type);
|
|
}
|
|
/* create new userdata. */
|
|
ud = (obj_udata *)lua_newuserdata(L, sizeof(obj_udata));
|
|
ud->obj = obj;
|
|
ud->flags = flags;
|
|
/* get obj_type metatable. */
|
|
lua_pushlightuserdata(L, type);
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */
|
|
lua_setmetatable(L, -2);
|
|
}
|
|
|
|
static FUNC_UNUSED void obj_udata_luapush_weak(lua_State *L, void *obj, obj_type *type, int flags) {
|
|
obj_udata *ud;
|
|
|
|
/* convert NULL's into Lua nil's. */
|
|
if(obj == NULL) {
|
|
lua_pushnil(L);
|
|
return;
|
|
}
|
|
/* check for type caster. */
|
|
if(type->dcaster) {
|
|
(type->dcaster)(&obj, &type);
|
|
}
|
|
/* get objects weak table. */
|
|
lua_pushlightuserdata(L, obj_udata_weak_ref_key);
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* weak ref table. */
|
|
/* lookup userdata instance from pointer. */
|
|
lua_pushlightuserdata(L, obj);
|
|
lua_rawget(L, -2);
|
|
if(!lua_isnil(L, -1)) {
|
|
lua_remove(L, -2); /* remove objects table. */
|
|
return;
|
|
}
|
|
lua_pop(L, 1); /* pop nil. */
|
|
|
|
/* create new userdata. */
|
|
ud = (obj_udata *)lua_newuserdata(L, sizeof(obj_udata));
|
|
|
|
/* init. obj_udata. */
|
|
ud->obj = obj;
|
|
ud->flags = flags;
|
|
/* get obj_type metatable. */
|
|
lua_pushlightuserdata(L, type);
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */
|
|
lua_setmetatable(L, -2);
|
|
|
|
/* add weak reference to object. */
|
|
lua_pushlightuserdata(L, obj); /* push object pointer as the 'key' */
|
|
lua_pushvalue(L, -2); /* push object's udata */
|
|
lua_rawset(L, -4); /* add weak reference to object. */
|
|
lua_remove(L, -2); /* remove objects table. */
|
|
}
|
|
|
|
/* default object equal method. */
|
|
static FUNC_UNUSED int obj_udata_default_equal(lua_State *L) {
|
|
obj_udata *ud1 = obj_udata_toobj(L, 1);
|
|
obj_udata *ud2 = obj_udata_toobj(L, 2);
|
|
|
|
lua_pushboolean(L, (ud1->obj == ud2->obj));
|
|
return 1;
|
|
}
|
|
|
|
/* default object tostring method. */
|
|
static FUNC_UNUSED int obj_udata_default_tostring(lua_State *L) {
|
|
obj_udata *ud = obj_udata_toobj(L, 1);
|
|
|
|
/* get object's metatable. */
|
|
lua_getmetatable(L, 1);
|
|
lua_remove(L, 1); /* remove userdata. */
|
|
/* get the object's name from the metatable */
|
|
lua_getfield(L, 1, ".name");
|
|
lua_remove(L, 1); /* remove metatable */
|
|
/* push object's pointer */
|
|
lua_pushfstring(L, ": %p, flags=%d", ud->obj, ud->flags);
|
|
lua_concat(L, 2);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Simple userdata objects.
|
|
*/
|
|
static FUNC_UNUSED void *obj_simple_udata_toobj(lua_State *L, int _index) {
|
|
void *ud;
|
|
|
|
/* make sure it's a userdata value. */
|
|
ud = lua_touserdata(L, _index);
|
|
if(ud == NULL) {
|
|
luaL_typerror(L, _index, "userdata"); /* is not a userdata value. */
|
|
}
|
|
return ud;
|
|
}
|
|
|
|
static FUNC_UNUSED void * obj_simple_udata_luacheck(lua_State *L, int _index, obj_type *type) {
|
|
void *ud;
|
|
/* make sure it's a userdata value. */
|
|
ud = lua_touserdata(L, _index);
|
|
if(ud != NULL) {
|
|
/* check object type by comparing metatables. */
|
|
if(lua_getmetatable(L, _index)) {
|
|
lua_pushlightuserdata(L, type);
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */
|
|
if(lua_rawequal(L, -1, -2)) {
|
|
lua_pop(L, 2); /* pop both metatables. */
|
|
return ud;
|
|
}
|
|
}
|
|
}
|
|
luaL_typerror(L, _index, type->name); /* is not a userdata value. */
|
|
return NULL;
|
|
}
|
|
|
|
static FUNC_UNUSED void * obj_simple_udata_luadelete(lua_State *L, int _index, obj_type *type, int *flags) {
|
|
void *obj;
|
|
obj = obj_simple_udata_luacheck(L, _index, type);
|
|
*flags = OBJ_UDATA_FLAG_OWN;
|
|
/* clear the metatable to invalidate userdata. */
|
|
lua_pushnil(L);
|
|
lua_setmetatable(L, _index);
|
|
return obj;
|
|
}
|
|
|
|
static FUNC_UNUSED void obj_simple_udata_luapush(lua_State *L, void *obj, int size, obj_type *type)
|
|
{
|
|
/* create new userdata. */
|
|
void *ud = lua_newuserdata(L, size);
|
|
memcpy(ud, obj, size);
|
|
/* get obj_type metatable. */
|
|
lua_pushlightuserdata(L, type);
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */
|
|
lua_setmetatable(L, -2);
|
|
}
|
|
|
|
/* default simple object equal method. */
|
|
static FUNC_UNUSED int obj_simple_udata_default_equal(lua_State *L) {
|
|
void *ud1 = obj_simple_udata_toobj(L, 1);
|
|
size_t len1 = lua_objlen(L, 1);
|
|
void *ud2 = obj_simple_udata_toobj(L, 2);
|
|
size_t len2 = lua_objlen(L, 2);
|
|
|
|
if(len1 == len2) {
|
|
lua_pushboolean(L, (memcmp(ud1, ud2, len1) == 0));
|
|
} else {
|
|
lua_pushboolean(L, 0);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* default simple object tostring method. */
|
|
static FUNC_UNUSED int obj_simple_udata_default_tostring(lua_State *L) {
|
|
void *ud = obj_simple_udata_toobj(L, 1);
|
|
|
|
/* get object's metatable. */
|
|
lua_getmetatable(L, 1);
|
|
lua_remove(L, 1); /* remove userdata. */
|
|
/* get the object's name from the metatable */
|
|
lua_getfield(L, 1, ".name");
|
|
lua_remove(L, 1); /* remove metatable */
|
|
/* push object's pointer */
|
|
lua_pushfstring(L, ": %p", ud);
|
|
lua_concat(L, 2);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int obj_constructor_call_wrapper(lua_State *L) {
|
|
/* replace '__call' table with constructor function. */
|
|
lua_pushvalue(L, lua_upvalueindex(1));
|
|
lua_replace(L, 1);
|
|
|
|
/* call constructor function with all parameters after the '__call' table. */
|
|
lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
|
|
/* return all results from constructor. */
|
|
return lua_gettop(L);
|
|
}
|
|
|
|
static void obj_type_register_constants(lua_State *L, const obj_const *constants, int tab_idx) {
|
|
/* register constants. */
|
|
while(constants->name != NULL) {
|
|
lua_pushstring(L, constants->name);
|
|
switch(constants->type) {
|
|
case CONST_BOOLEAN:
|
|
lua_pushboolean(L, constants->num != 0.0);
|
|
break;
|
|
case CONST_NUMBER:
|
|
lua_pushnumber(L, constants->num);
|
|
break;
|
|
case CONST_STRING:
|
|
lua_pushstring(L, constants->str);
|
|
break;
|
|
default:
|
|
lua_pushnil(L);
|
|
break;
|
|
}
|
|
lua_rawset(L, tab_idx - 2);
|
|
constants++;
|
|
}
|
|
}
|
|
|
|
static void obj_type_register_package(lua_State *L, const reg_sub_module *type_reg) {
|
|
obj_type *type = type_reg->type;
|
|
const luaL_reg *reg_list = type_reg->pub_funcs;
|
|
|
|
/* create public functions table. */
|
|
if(reg_list != NULL && reg_list[0].name != NULL) {
|
|
/* register functions */
|
|
luaL_register(L, NULL, reg_list);
|
|
}
|
|
|
|
obj_type_register_constants(L, type_reg->constants, -1);
|
|
|
|
lua_pop(L, 1); /* drop package table */
|
|
}
|
|
|
|
static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int priv_table) {
|
|
const luaL_reg *reg_list;
|
|
obj_type *type = type_reg->type;
|
|
const obj_base *base = type_reg->bases;
|
|
|
|
if(type_reg->is_package == 1) {
|
|
return obj_type_register_package(L, type_reg);
|
|
}
|
|
|
|
/* create public functions table. */
|
|
reg_list = type_reg->pub_funcs;
|
|
if(reg_list != NULL && reg_list[0].name != NULL) {
|
|
/* register "constructors" as to object's public API */
|
|
luaL_register(L, NULL, reg_list); /* fill public API table. */
|
|
|
|
/* make public API table callable as the default constructor. */
|
|
lua_newtable(L); /* create metatable */
|
|
lua_pushliteral(L, "__call");
|
|
lua_pushcfunction(L, reg_list[0].func); /* push first constructor function. */
|
|
lua_pushcclosure(L, obj_constructor_call_wrapper, 1); /* make __call wrapper. */
|
|
lua_rawset(L, -3); /* metatable.__call = <default constructor> */
|
|
lua_setmetatable(L, -2);
|
|
|
|
lua_pop(L, 1); /* pop public API table, don't need it any more. */
|
|
/* create methods table. */
|
|
lua_newtable(L);
|
|
} else {
|
|
/* register all methods as public functions. */
|
|
}
|
|
|
|
luaL_register(L, NULL, type_reg->methods); /* fill methods table. */
|
|
|
|
luaL_newmetatable(L, type->name); /* create metatable */
|
|
lua_pushliteral(L, ".name");
|
|
lua_pushstring(L, type->name);
|
|
lua_rawset(L, -3); /* metatable['.name'] = "<object_name>" */
|
|
lua_pushliteral(L, ".type");
|
|
lua_pushlightuserdata(L, type);
|
|
lua_rawset(L, -3); /* metatable['.type'] = lightuserdata -> obj_type */
|
|
lua_pushlightuserdata(L, type);
|
|
lua_pushvalue(L, -2); /* dup metatable. */
|
|
lua_rawset(L, LUA_REGISTRYINDEX); /* REGISTRY[type] = metatable */
|
|
|
|
#if LUAJIT_FFI
|
|
/* add metatable to 'priv_table' */
|
|
lua_pushstring(L, type->name);
|
|
lua_pushvalue(L, -2); /* dup metatable. */
|
|
lua_rawset(L, priv_table); /* priv_table["<object_name>"] = metatable */
|
|
#endif
|
|
|
|
luaL_register(L, NULL, type_reg->metas); /* fill metatable */
|
|
|
|
/* add obj_bases to metatable. */
|
|
while(base->id >= 0) {
|
|
lua_pushlightuserdata(L, (void *)base);
|
|
lua_rawseti(L, -2, base->id);
|
|
base++;
|
|
}
|
|
|
|
obj_type_register_constants(L, type_reg->constants, -2);
|
|
|
|
lua_pushliteral(L, "__index");
|
|
lua_pushvalue(L, -3); /* dup methods table */
|
|
lua_rawset(L, -3); /* metatable.__index = methods */
|
|
#if OBJ_DATA_HIDDEN_METATABLE
|
|
lua_pushliteral(L, "__metatable");
|
|
lua_pushvalue(L, -3); /* dup methods table */
|
|
lua_rawset(L, -3); /* hide metatable:
|
|
metatable.__metatable = methods */
|
|
#endif
|
|
lua_pop(L, 2); /* drop metatable & methods */
|
|
}
|
|
|
|
static FUNC_UNUSED int lua_checktype_ref(lua_State *L, int _index, int _type) {
|
|
luaL_checktype(L,_index,_type);
|
|
lua_pushvalue(L,_index);
|
|
return luaL_ref(L, LUA_REGISTRYINDEX);
|
|
}
|
|
|
|
#if LUAJIT_FFI
|
|
static int nobj_udata_new_ffi(lua_State *L) {
|
|
size_t size = luaL_checkinteger(L, 1);
|
|
void *ud;
|
|
luaL_checktype(L, 2, LUA_TTABLE);
|
|
lua_settop(L, 2);
|
|
/* create userdata. */
|
|
ud = lua_newuserdata(L, size);
|
|
lua_replace(L, 1);
|
|
/* set userdata's metatable. */
|
|
lua_setmetatable(L, 1);
|
|
return 1;
|
|
}
|
|
|
|
static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name,
|
|
const char *ffi_init_code, const ffi_export_symbol *ffi_exports, int priv_table)
|
|
{
|
|
int err;
|
|
|
|
/* export symbols to priv_table. */
|
|
while(ffi_exports->name != NULL) {
|
|
lua_pushstring(L, ffi_exports->name);
|
|
lua_pushlightuserdata(L, ffi_exports->sym);
|
|
lua_settable(L, priv_table);
|
|
ffi_exports++;
|
|
}
|
|
err = luaL_loadbuffer(L, ffi_init_code, strlen(ffi_init_code), ffi_mod_name);
|
|
if(0 == err) {
|
|
lua_pushvalue(L, -2); /* dup C module's table. */
|
|
lua_pushvalue(L, priv_table); /* move priv_table to top of stack. */
|
|
lua_remove(L, priv_table);
|
|
lua_pushcfunction(L, nobj_udata_new_ffi);
|
|
err = lua_pcall(L, 3, 0, 0);
|
|
}
|
|
if(err) {
|
|
const char *msg = "<err not a string>";
|
|
if(lua_isstring(L, -1)) {
|
|
msg = lua_tostring(L, -1);
|
|
}
|
|
printf("Failed to install FFI-based bindings: %s\n", msg);
|
|
lua_pop(L, 1); /* pop error message. */
|
|
}
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
|
|
static const char zmq_ffi_lua_code[] = "\
|
|
local _M, _priv, udata_new = ...\n\
|
|
\n\
|
|
local band = bit.band\n\
|
|
local d_getmetatable = debug.getmetatable\n\
|
|
local d_setmetatable = debug.setmetatable\n\
|
|
\n\
|
|
-- try loading luajit's ffi\n\
|
|
local stat, ffi=pcall(require,\"ffi\")\n\
|
|
if not stat then\n\
|
|
return\n\
|
|
end\n\
|
|
-- check if ffi is disabled.\n\
|
|
if disable_ffi then\n\
|
|
print(\"FFI disabled: Using standard Lua api interface.\")\n\
|
|
return\n\
|
|
end\n\
|
|
\n\
|
|
local OBJ_UDATA_FLAG_OWN = 1\n\
|
|
local OBJ_UDATA_FLAG_LOOKUP = 2\n\
|
|
local OBJ_UDATA_LAST_FLAG = OBJ_UDATA_FLAG_LOOKUP\n\
|
|
\n\
|
|
local OBJ_TYPE_FLAG_WEAK_REF = 1\n\
|
|
local OBJ_TYPE_SIMPLE = 2\n\
|
|
\n\
|
|
ffi.cdef[[\n\
|
|
\n\
|
|
typedef struct obj_type obj_type;\n\
|
|
\n\
|
|
typedef void (*base_caster_t)(void **obj);\n\
|
|
\n\
|
|
typedef void (*dyn_caster_t)(void **obj, obj_type **type);\n\
|
|
\n\
|
|
struct obj_type {\n\
|
|
dyn_caster_t dcaster; /**< caster to support casting to sub-objects. */\n\
|
|
int32_t id; /**< type's id. */\n\
|
|
uint32_t flags; /**< type's flags (weak refs) */\n\
|
|
const char *name; /**< type's object name. */\n\
|
|
};\n\
|
|
\n\
|
|
typedef struct obj_base {\n\
|
|
int32_t id;\n\
|
|
base_caster_t bcaster;\n\
|
|
} obj_base;\n\
|
|
\n\
|
|
typedef struct obj_udata {\n\
|
|
void *obj;\n\
|
|
uint32_t flags; /**< lua_own:1bit */\n\
|
|
} obj_udata;\n\
|
|
\n\
|
|
]]\n\
|
|
\n\
|
|
local obj_type_ptr = ffi.typeof\"obj_type *\"\n\
|
|
local obj_udata_ptr = ffi.typeof\"obj_udata *\"\n\
|
|
local obj_simple_udata_ptr = ffi.typeof\"void *\"\n\
|
|
local obj_udata_size = ffi.sizeof\"obj_udata\"\n\
|
|
\n\
|
|
-- cache mapping of cdata to userdata\n\
|
|
local weak_objects = setmetatable({}, { __mode = \"v\" })\n\
|
|
\n\
|
|
local function obj_udata_luacheck_internal(obj, type_mt)\n\
|
|
local obj_mt = d_getmetatable(obj)\n\
|
|
if obj_mt == type_mt then\n\
|
|
-- convert userdata to cdata.\n\
|
|
return obj_udata_ptr(obj)\n\
|
|
end\n\
|
|
error(\"(expected `\" .. type_mt['.name'] .. \"`, got \" .. type(obj) .. \")\", 3)\n\
|
|
end\n\
|
|
\n\
|
|
local function obj_udata_luacheck(obj, type_mt)\n\
|
|
local ud = obj_udata_luacheck_internal(obj, type_mt)\n\
|
|
return ud.obj\n\
|
|
end\n\
|
|
\n\
|
|
local function obj_udata_luadelete(ud_obj, type_mt)\n\
|
|
local ud = obj_udata_luacheck_internal(ud_obj, type_mt)\n\
|
|
local obj, flags = ud.obj, ud.flags\n\
|
|
-- null userdata.\n\
|
|
ud.obj = nil\n\
|
|
ud.flags = 0\n\
|
|
-- invalid userdata, by setting the metatable to nil.\n\
|
|
d_setmetatable(ud_obj, nil)\n\
|
|
return obj, flags\n\
|
|
end\n\
|
|
\n\
|
|
local function obj_udata_luapush(obj, type_mt, obj_type, flags)\n\
|
|
if obj == nil then return end\n\
|
|
\n\
|
|
-- apply type's dynamic caster.\n\
|
|
if obj_type.dcaster ~= nil then\n\
|
|
local obj_ptr = ffi.new(\"void *[1]\", obj)\n\
|
|
local type_ptr = ffi.new(\"obj_type *[1]\", obj_type)\n\
|
|
obj_type.dcaster(obj_ptr, type_ptr)\n\
|
|
obj = obj_ptr[1]\n\
|
|
type = type_ptr[1]\n\
|
|
end\n\
|
|
\n\
|
|
-- create new userdata\n\
|
|
ud_obj = udata_new(obj_udata_size, type_mt)\n\
|
|
local ud = obj_udata_ptr(ud_obj)\n\
|
|
-- init. object\n\
|
|
ud.obj = obj\n\
|
|
ud.flags = flags\n\
|
|
\n\
|
|
return ud_obj\n\
|
|
end\n\
|
|
\n\
|
|
local function obj_udata_luapush_weak(obj, type_mt, obj_type, flags)\n\
|
|
if obj == nil then return end\n\
|
|
\n\
|
|
-- apply type's dynamic caster.\n\
|
|
if obj_type.dcaster ~= nil then\n\
|
|
local obj_ptr = ffi.new(\"void *[1]\", obj)\n\
|
|
local type_ptr = ffi.new(\"obj_type *[1]\", obj_type)\n\
|
|
obj_type.dcaster(obj_ptr, type_ptr)\n\
|
|
obj = obj_ptr[1]\n\
|
|
type = type_ptr[1]\n\
|
|
end\n\
|
|
\n\
|
|
-- lookup object in weak ref. table.\n\
|
|
local obj_key = tonumber(ffi.cast('uintptr_t', obj))\n\
|
|
local ud_obj = weak_objects[obj_key]\n\
|
|
if ud_obj ~= nil then return ud_obj end\n\
|
|
\n\
|
|
-- create new userdata\n\
|
|
ud_obj = udata_new(obj_udata_size, type_mt)\n\
|
|
local ud = obj_udata_ptr(ud_obj)\n\
|
|
-- init. object\n\
|
|
ud.obj = obj\n\
|
|
ud.flags = flags\n\
|
|
\n\
|
|
-- cache weak reference to object.\n\
|
|
weak_objects[obj_key] = ud_obj\n\
|
|
\n\
|
|
return ud_obj\n\
|
|
end\n\
|
|
\n\
|
|
local function obj_simple_udata_luacheck(ud_obj, type_mt)\n\
|
|
local obj_mt = d_getmetatable(ud_obj)\n\
|
|
if obj_mt == type_mt then\n\
|
|
-- convert userdata to cdata.\n\
|
|
return obj_simple_udata_ptr(ud_obj)\n\
|
|
end\n\
|
|
error(\"(expected `\" .. type_mt['.name'] .. \"`, got \" .. type(ud_obj) .. \")\", 3)\n\
|
|
end\n\
|
|
\n\
|
|
local function obj_simple_udata_luadelete(ud_obj, type_mt)\n\
|
|
local c_obj = obj_simple_udata_luacheck(ud_obj, type_mt)\n\
|
|
-- invalid userdata, by setting the metatable to nil.\n\
|
|
d_setmetatable(ud_obj, nil)\n\
|
|
return c_obj, OBJ_UDATA_FLAG_OWN\n\
|
|
end\n\
|
|
\n\
|
|
local function obj_simple_udata_luapush(c_obj, size, type_mt)\n\
|
|
if c_obj == nil then return end\n\
|
|
\n\
|
|
-- create new userdata\n\
|
|
ud_obj = udata_new(size, type_mt)\n\
|
|
local data = obj_simple_udata_ptr(ud_obj)\n\
|
|
-- init. object\n\
|
|
ffi.copy(data, c_obj, size)\n\
|
|
\n\
|
|
return ud_obj\n\
|
|
end\n\
|
|
\n\
|
|
ffi.cdef[[\n\
|
|
typedef const char * (*get_zmq_strerror_func)();\n\
|
|
\n\
|
|
typedef int ZMQ_Error;\n\
|
|
\n\
|
|
\n\
|
|
typedef struct zmq_msg_t\n\
|
|
{\n\
|
|
void *content;\n\
|
|
unsigned char flags;\n\
|
|
unsigned char vsm_size;\n\
|
|
unsigned char vsm_data [30]; /* that '30' is from 'MAX_VSM_SIZE' */\n\
|
|
} zmq_msg_t;\n\
|
|
\n\
|
|
typedef void (zmq_free_fn) (void *data, void *hint);\n\
|
|
\n\
|
|
int zmq_msg_init (zmq_msg_t *msg);\n\
|
|
int zmq_msg_init_size (zmq_msg_t *msg, size_t size);\n\
|
|
int zmq_msg_init_data (zmq_msg_t *msg, void *data, size_t size, zmq_free_fn *ffn, void *hint);\n\
|
|
\n\
|
|
\n\
|
|
ZMQ_Error zmq_msg_close(zmq_msg_t * this);\n\
|
|
\n\
|
|
ZMQ_Error zmq_msg_close(zmq_msg_t * this);\n\
|
|
\n\
|
|
ZMQ_Error zmq_msg_move(zmq_msg_t * this, zmq_msg_t * src);\n\
|
|
\n\
|
|
ZMQ_Error zmq_msg_copy(zmq_msg_t * this, zmq_msg_t * src);\n\
|
|
\n\
|
|
void * zmq_msg_data(zmq_msg_t * this);\n\
|
|
\n\
|
|
size_t zmq_msg_size(zmq_msg_t * this);\n\
|
|
\n\
|
|
typedef void * ZMQ_Socket;\n\
|
|
\n\
|
|
ZMQ_Error zmq_close(ZMQ_Socket * this);\n\
|
|
\n\
|
|
ZMQ_Error zmq_bind(ZMQ_Socket * this, const char * addr);\n\
|
|
\n\
|
|
ZMQ_Error zmq_connect(ZMQ_Socket * this, const char * addr);\n\
|
|
\n\
|
|
int zmq_setsockopt (void *s, int option, const void *optval, size_t optvallen);\n\
|
|
int zmq_getsockopt (void *s, int option, void *optval, size_t *optvallen);\n\
|
|
\n\
|
|
ZMQ_Error zmq_send(ZMQ_Socket * this, zmq_msg_t * msg, int flags);\n\
|
|
\n\
|
|
typedef ZMQ_Error (*simple_zmq_send_func)(ZMQ_Socket sock, const char *data, size_t data_len, int flags);\n\
|
|
\n\
|
|
ZMQ_Error zmq_recv(ZMQ_Socket * this, zmq_msg_t * msg, int flags);\n\
|
|
\n\
|
|
typedef void * ZMQ_Ctx;\n\
|
|
\n\
|
|
ZMQ_Error zmq_term(ZMQ_Ctx * this);\n\
|
|
\n\
|
|
ZMQ_Socket zmq_socket(ZMQ_Ctx * this, int type);\n\
|
|
\n\
|
|
ZMQ_Ctx zmq_init(int io_threads);\n\
|
|
\n\
|
|
ZMQ_Error zmq_device(int device, ZMQ_Socket insock, ZMQ_Socket outsock);\n\
|
|
\n\
|
|
\n\
|
|
]]\n\
|
|
\n\
|
|
local zmq_msg_t_mt = _priv[\"zmq_msg_t\"]\n\
|
|
local zmq_msg_t_type = obj_type_ptr(zmq_msg_t_mt[\".type\"])\n\
|
|
local zmq_msg_t_meth = zmq_msg_t_mt.__index\n\
|
|
local zmq_msg_t_objects = setmetatable({}, { __mode = \"k\" })\n\
|
|
\n\
|
|
local function obj_type_zmq_msg_t_check(ud_obj)\n\
|
|
local c_obj = zmq_msg_t_objects[ud_obj]\n\
|
|
if c_obj == nil then\n\
|
|
-- cdata object not in cache\n\
|
|
c_obj = obj_simple_udata_luacheck(ud_obj, zmq_msg_t_mt)\n\
|
|
zmq_msg_t_objects[ud_obj] = c_obj\n\
|
|
end\n\
|
|
return c_obj\n\
|
|
end\n\
|
|
\n\
|
|
local function obj_type_zmq_msg_t_delete(ud_obj)\n\
|
|
zmq_msg_t_objects[ud_obj] = nil\n\
|
|
return obj_simple_udata_luadelete(ud_obj, zmq_msg_t_mt)\n\
|
|
end\n\
|
|
\n\
|
|
local zmq_msg_t_sizeof = ffi.sizeof\"zmq_msg_t\"\n\
|
|
local function obj_type_zmq_msg_t_push(c_obj)\n\
|
|
local ud_obj = obj_simple_udata_luapush(c_obj, zmq_msg_t_sizeof, zmq_msg_t_mt)\n\
|
|
zmq_msg_t_objects[ud_obj] = c_obj\n\
|
|
return ud_obj\n\
|
|
end\n\
|
|
\n\
|
|
\n\
|
|
local ZMQ_Socket_mt = _priv[\"ZMQ_Socket\"]\n\
|
|
local ZMQ_Socket_type = obj_type_ptr(ZMQ_Socket_mt[\".type\"])\n\
|
|
local ZMQ_Socket_meth = ZMQ_Socket_mt.__index\n\
|
|
local ZMQ_Socket_objects = setmetatable({}, { __mode = \"k\" })\n\
|
|
\n\
|
|
local function obj_type_ZMQ_Socket_check(ud_obj)\n\
|
|
local c_obj = ZMQ_Socket_objects[ud_obj]\n\
|
|
if c_obj == nil then\n\
|
|
-- cdata object not in cache\n\
|
|
c_obj = obj_udata_luacheck(ud_obj, ZMQ_Socket_mt)\n\
|
|
ZMQ_Socket_objects[ud_obj] = c_obj\n\
|
|
end\n\
|
|
return c_obj\n\
|
|
end\n\
|
|
\n\
|
|
local function obj_type_ZMQ_Socket_delete(ud_obj)\n\
|
|
ZMQ_Socket_objects[ud_obj] = nil\n\
|
|
return obj_udata_luadelete(ud_obj, ZMQ_Socket_mt)\n\
|
|
end\n\
|
|
\n\
|
|
local function obj_type_ZMQ_Socket_push(c_obj, flags)\n\
|
|
local ud_obj = obj_udata_luapush_weak(c_obj, ZMQ_Socket_mt, ZMQ_Socket_type, flags)\n\
|
|
ZMQ_Socket_objects[ud_obj] = c_obj\n\
|
|
return ud_obj\n\
|
|
end\n\
|
|
\n\
|
|
\n\
|
|
local ZMQ_Ctx_mt = _priv[\"ZMQ_Ctx\"]\n\
|
|
local ZMQ_Ctx_type = obj_type_ptr(ZMQ_Ctx_mt[\".type\"])\n\
|
|
local ZMQ_Ctx_meth = ZMQ_Ctx_mt.__index\n\
|
|
local ZMQ_Ctx_objects = setmetatable({}, { __mode = \"k\" })\n\
|
|
\n\
|
|
local function obj_type_ZMQ_Ctx_check(ud_obj)\n\
|
|
local c_obj = ZMQ_Ctx_objects[ud_obj]\n\
|
|
if c_obj == nil then\n\
|
|
-- cdata object not in cache\n\
|
|
c_obj = obj_udata_luacheck(ud_obj, ZMQ_Ctx_mt)\n\
|
|
ZMQ_Ctx_objects[ud_obj] = c_obj\n\
|
|
end\n\
|
|
return c_obj\n\
|
|
end\n\
|
|
\n\
|
|
local function obj_type_ZMQ_Ctx_delete(ud_obj)\n\
|
|
ZMQ_Ctx_objects[ud_obj] = nil\n\
|
|
return obj_udata_luadelete(ud_obj, ZMQ_Ctx_mt)\n\
|
|
end\n\
|
|
\n\
|
|
local function obj_type_ZMQ_Ctx_push(c_obj, flags)\n\
|
|
local ud_obj = obj_udata_luapush_weak(c_obj, ZMQ_Ctx_mt, ZMQ_Ctx_type, flags)\n\
|
|
ZMQ_Ctx_objects[ud_obj] = c_obj\n\
|
|
return ud_obj\n\
|
|
end\n\
|
|
\n\
|
|
\n\
|
|
local zmq_mt = _M\n\
|
|
local zmq_meth = _M\n\
|
|
local zmq_func = _M\n\
|
|
\n\
|
|
\n\
|
|
local C = ffi.load(\"zmq\",false)\n\
|
|
\n\
|
|
local OBJ_UDATA_CTX_SHOULD_FREE = (OBJ_UDATA_LAST_FLAG * 2)\n\
|
|
\n\
|
|
local get_zmq_strerror = ffi.new(\"get_zmq_strerror_func\", _priv[\"get_zmq_strerror\"])\n\
|
|
\n\
|
|
local C_get_zmq_strerror = get_zmq_strerror\n\
|
|
-- make nicer wrapper for exported error function.\n\
|
|
local function get_zmq_strerror()\n\
|
|
return ffi.string(C_get_zmq_strerror())\n\
|
|
end\n\
|
|
\n\
|
|
local function error_code__ZMQ_Error__push(err)\n\
|
|
local err_str\n\
|
|
if(0 ~= err) then\n\
|
|
err_str = get_zmq_strerror();\n\
|
|
end\n\
|
|
\n\
|
|
return err_str\n\
|
|
end\n\
|
|
\n\
|
|
\n\
|
|
-- Start \"zmq_msg_t\" FFI interface\n\
|
|
-- method: delete\n\
|
|
function zmq_msg_t_meth.delete(self)\n\
|
|
local this,this_flags = obj_type_zmq_msg_t_delete(self)\n\
|
|
if(band(this_flags,OBJ_UDATA_FLAG_OWN) == 0) then return end\n\
|
|
local rc_zmq_msg_close\n\
|
|
rc_zmq_msg_close = C.zmq_msg_close(this)\n\
|
|
-- check for error.\n\
|
|
local rc_zmq_msg_close_err\n\
|
|
if (0 ~= rc_zmq_msg_close) then\n\
|
|
rc_zmq_msg_close = false\n\
|
|
rc_zmq_msg_close_err = error_code__ZMQ_Error__push(rc_zmq_msg_close)\n\
|
|
else\n\
|
|
rc_zmq_msg_close = true\n\
|
|
end\n\
|
|
return rc_zmq_msg_close, rc_zmq_msg_close_err\n\
|
|
end\n\
|
|
\n\
|
|
-- method: close\n\
|
|
function zmq_msg_t_meth.close(self)\n\
|
|
local this = obj_type_zmq_msg_t_check(self)\n\
|
|
local rc_zmq_msg_close\n\
|
|
rc_zmq_msg_close = C.zmq_msg_close(this)\n\
|
|
-- check for error.\n\
|
|
local rc_zmq_msg_close_err\n\
|
|
if (0 ~= rc_zmq_msg_close) then\n\
|
|
rc_zmq_msg_close = false\n\
|
|
rc_zmq_msg_close_err = error_code__ZMQ_Error__push(rc_zmq_msg_close)\n\
|
|
else\n\
|
|
rc_zmq_msg_close = true\n\
|
|
end\n\
|
|
return rc_zmq_msg_close, rc_zmq_msg_close_err\n\
|
|
end\n\
|
|
\n\
|
|
-- method: move\n\
|
|
function zmq_msg_t_meth.move(self, src)\n\
|
|
local this = obj_type_zmq_msg_t_check(self)\n\
|
|
src = obj_type_zmq_msg_t_check(src)\n\
|
|
local rc_zmq_msg_move\n\
|
|
rc_zmq_msg_move = C.zmq_msg_move(this, src)\n\
|
|
-- check for error.\n\
|
|
local rc_zmq_msg_move_err\n\
|
|
if (0 ~= rc_zmq_msg_move) then\n\
|
|
rc_zmq_msg_move = false\n\
|
|
rc_zmq_msg_move_err = error_code__ZMQ_Error__push(rc_zmq_msg_move)\n\
|
|
else\n\
|
|
rc_zmq_msg_move = true\n\
|
|
end\n\
|
|
return rc_zmq_msg_move, rc_zmq_msg_move_err\n\
|
|
end\n\
|
|
\n\
|
|
-- method: copy\n\
|
|
function zmq_msg_t_meth.copy(self, src)\n\
|
|
local this = obj_type_zmq_msg_t_check(self)\n\
|
|
src = obj_type_zmq_msg_t_check(src)\n\
|
|
local rc_zmq_msg_copy\n\
|
|
rc_zmq_msg_copy = C.zmq_msg_copy(this, src)\n\
|
|
-- check for error.\n\
|
|
local rc_zmq_msg_copy_err\n\
|
|
if (0 ~= rc_zmq_msg_copy) then\n\
|
|
rc_zmq_msg_copy = false\n\
|
|
rc_zmq_msg_copy_err = error_code__ZMQ_Error__push(rc_zmq_msg_copy)\n\
|
|
else\n\
|
|
rc_zmq_msg_copy = true\n\
|
|
end\n\
|
|
return rc_zmq_msg_copy, rc_zmq_msg_copy_err\n\
|
|
end\n\
|
|
\n\
|
|
-- method: set_data\n\
|
|
function zmq_msg_t_meth.set_data(self, data)\n\
|
|
local this = obj_type_zmq_msg_t_check(self)\n\
|
|
local data_len = #data\n\
|
|
local err\n\
|
|
-- check message data size.\n\
|
|
if (C.zmq_msg_size(this) ~= data_len) then\n\
|
|
-- need to resize message.\n\
|
|
C.zmq_msg_close(this); -- close old message, to free old data.\n\
|
|
err = C.zmq_msg_init_size(this, data_len); -- re-initialize message.\n\
|
|
if (0 ~= err) then\n\
|
|
error(\"set_data() failed: \" .. get_zmq_strerror());\n\
|
|
end\n\
|
|
end\n\
|
|
-- copy data into message\n\
|
|
ffi.copy(C.zmq_msg_data(this), data, data_len);\n\
|
|
\n\
|
|
-- check for error.\n\
|
|
local err_err\n\
|
|
if (0 ~= err) then\n\
|
|
err = false\n\
|
|
err_err = error_code__ZMQ_Error__push(err)\n\
|
|
else\n\
|
|
err = true\n\
|
|
end\n\
|
|
return err, err_err\n\
|
|
end\n\
|
|
\n\
|
|
-- method: data\n\
|
|
function zmq_msg_t_meth.data(self)\n\
|
|
local this = obj_type_zmq_msg_t_check(self)\n\
|
|
local rc_zmq_msg_data\n\
|
|
rc_zmq_msg_data = C.zmq_msg_data(this)\n\
|
|
rc_zmq_msg_data = rc_zmq_msg_data\n\
|
|
return rc_zmq_msg_data\n\
|
|
end\n\
|
|
\n\
|
|
-- method: set_size\n\
|
|
function zmq_msg_t_meth.set_size(self, size)\n\
|
|
local this = obj_type_zmq_msg_t_check(self)\n\
|
|
\n\
|
|
local err\n\
|
|
-- check message data size.\n\
|
|
if (C.zmq_msg_size(this) ~= size) then\n\
|
|
-- need to resize message.\n\
|
|
C.zmq_msg_close(this); -- close old message, to free old data.\n\
|
|
err = C.zmq_msg_init_size(this, size); -- re-initialize message.\n\
|
|
if (0 ~= err) then\n\
|
|
error(\"set_size() failed: \" .. get_zmq_strerror());\n\
|
|
end\n\
|
|
end\n\
|
|
\n\
|
|
-- check for error.\n\
|
|
local err_err\n\
|
|
if (0 ~= err) then\n\
|
|
err = false\n\
|
|
err_err = error_code__ZMQ_Error__push(err)\n\
|
|
else\n\
|
|
err = true\n\
|
|
end\n\
|
|
return err, err_err\n\
|
|
end\n\
|
|
\n\
|
|
-- method: size\n\
|
|
function zmq_msg_t_meth.size(self)\n\
|
|
local this = obj_type_zmq_msg_t_check(self)\n\
|
|
local rc_zmq_msg_size\n\
|
|
rc_zmq_msg_size = C.zmq_msg_size(this)\n\
|
|
rc_zmq_msg_size = rc_zmq_msg_size\n\
|
|
return rc_zmq_msg_size\n\
|
|
end\n\
|
|
\n\
|
|
-- method: __tostring\n\
|
|
function zmq_msg_t_mt.__tostring(self)\n\
|
|
local this = obj_type_zmq_msg_t_check(self)\n\
|
|
local data_len = 0\n\
|
|
local data\n\
|
|
data = zmq_msg_data(this);\n\
|
|
data_len = zmq_msg_size(this);\n\
|
|
\n\
|
|
data = ((nil ~= data) and ffi.string(data,data_len))\n\
|
|
return data\n\
|
|
end\n\
|
|
\n\
|
|
-- End \"zmq_msg_t\" FFI interface\n\
|
|
\n\
|
|
\n\
|
|
-- Start \"ZMQ_Socket\" FFI interface\n\
|
|
-- method: close\n\
|
|
function ZMQ_Socket_meth.close(self)\n\
|
|
local this,this_flags = obj_type_ZMQ_Socket_delete(self)\n\
|
|
if(band(this_flags,OBJ_UDATA_FLAG_OWN) == 0) then return end\n\
|
|
local rc_zmq_close\n\
|
|
rc_zmq_close = C.zmq_close(this)\n\
|
|
-- check for error.\n\
|
|
local rc_zmq_close_err\n\
|
|
if (0 ~= rc_zmq_close) then\n\
|
|
rc_zmq_close = false\n\
|
|
rc_zmq_close_err = error_code__ZMQ_Error__push(rc_zmq_close)\n\
|
|
else\n\
|
|
rc_zmq_close = true\n\
|
|
end\n\
|
|
return rc_zmq_close, rc_zmq_close_err\n\
|
|
end\n\
|
|
\n\
|
|
-- method: bind\n\
|
|
function ZMQ_Socket_meth.bind(self, addr)\n\
|
|
local this = obj_type_ZMQ_Socket_check(self)\n\
|
|
local addr_len = #addr\n\
|
|
local rc_zmq_bind\n\
|
|
rc_zmq_bind = C.zmq_bind(this, addr)\n\
|
|
-- check for error.\n\
|
|
local rc_zmq_bind_err\n\
|
|
if (0 ~= rc_zmq_bind) then\n\
|
|
rc_zmq_bind = false\n\
|
|
rc_zmq_bind_err = error_code__ZMQ_Error__push(rc_zmq_bind)\n\
|
|
else\n\
|
|
rc_zmq_bind = true\n\
|
|
end\n\
|
|
return rc_zmq_bind, rc_zmq_bind_err\n\
|
|
end\n\
|
|
\n\
|
|
-- method: connect\n\
|
|
function ZMQ_Socket_meth.connect(self, addr)\n\
|
|
local this = obj_type_ZMQ_Socket_check(self)\n\
|
|
local addr_len = #addr\n\
|
|
local rc_zmq_connect\n\
|
|
rc_zmq_connect = C.zmq_connect(this, addr)\n\
|
|
-- check for error.\n\
|
|
local rc_zmq_connect_err\n\
|
|
if (0 ~= rc_zmq_connect) then\n\
|
|
rc_zmq_connect = false\n\
|
|
rc_zmq_connect_err = error_code__ZMQ_Error__push(rc_zmq_connect)\n\
|
|
else\n\
|
|
rc_zmq_connect = true\n\
|
|
end\n\
|
|
return rc_zmq_connect, rc_zmq_connect_err\n\
|
|
end\n\
|
|
\n\
|
|
-- temp. values for 'events' function.\n\
|
|
local events_tmp = ffi.new('uint32_t[1]', 0)\n\
|
|
local events_tmp_size = ffi.sizeof('uint32_t')\n\
|
|
local events_tmp_len = ffi.new('size_t[1]', events_tmp_size)\n\
|
|
local ZMQ_EVENTS = _M.EVENTS\n\
|
|
\n\
|
|
-- method: events\n\
|
|
function ZMQ_Socket_meth.events(self)\n\
|
|
local this = obj_type_ZMQ_Socket_check(self)\n\
|
|
local events\n\
|
|
local err\n\
|
|
events_tmp_len[0] = events_tmp_size\n\
|
|
err = C.zmq_getsockopt(this, ZMQ_EVENTS, events_tmp, events_tmp_len);\n\
|
|
events = events_tmp[0]\n\
|
|
\n\
|
|
if not (0 ~= err) then\n\
|
|
events = events\n\
|
|
else\n\
|
|
events = nil\n\
|
|
end\n\
|
|
err = error_code__ZMQ_Error__push(err)\n\
|
|
return events, err\n\
|
|
end\n\
|
|
\n\
|
|
-- method: send_msg\n\
|
|
function ZMQ_Socket_meth.send_msg(self, msg, flags)\n\
|
|
local this = obj_type_ZMQ_Socket_check(self)\n\
|
|
msg = obj_type_zmq_msg_t_check(msg)\n\
|
|
flags = flags or 0\n\
|
|
local rc_zmq_send\n\
|
|
rc_zmq_send = C.zmq_send(this, msg, flags)\n\
|
|
-- check for error.\n\
|
|
local rc_zmq_send_err\n\
|
|
if (0 ~= rc_zmq_send) then\n\
|
|
rc_zmq_send = false\n\
|
|
rc_zmq_send_err = error_code__ZMQ_Error__push(rc_zmq_send)\n\
|
|
else\n\
|
|
rc_zmq_send = true\n\
|
|
end\n\
|
|
return rc_zmq_send, rc_zmq_send_err\n\
|
|
end\n\
|
|
\n\
|
|
local simple_zmq_send = ffi.new(\"simple_zmq_send_func\", _priv[\"simple_zmq_send\"])\n\
|
|
\n\
|
|
-- method: send\n\
|
|
function ZMQ_Socket_meth.send(self, data, flags)\n\
|
|
local this = obj_type_ZMQ_Socket_check(self)\n\
|
|
local data_len = #data\n\
|
|
flags = flags or 0\n\
|
|
local err\n\
|
|
err = simple_zmq_send(this, data, data_len, flags);\n\
|
|
\n\
|
|
-- check for error.\n\
|
|
local err_err\n\
|
|
if (0 ~= err) then\n\
|
|
err = false\n\
|
|
err_err = error_code__ZMQ_Error__push(err)\n\
|
|
else\n\
|
|
err = true\n\
|
|
end\n\
|
|
return err, err_err\n\
|
|
end\n\
|
|
\n\
|
|
-- method: recv_msg\n\
|
|
function ZMQ_Socket_meth.recv_msg(self, msg, flags)\n\
|
|
local this = obj_type_ZMQ_Socket_check(self)\n\
|
|
msg = obj_type_zmq_msg_t_check(msg)\n\
|
|
flags = flags or 0\n\
|
|
local rc_zmq_recv\n\
|
|
rc_zmq_recv = C.zmq_recv(this, msg, flags)\n\
|
|
-- check for error.\n\
|
|
local rc_zmq_recv_err\n\
|
|
if (0 ~= rc_zmq_recv) then\n\
|
|
rc_zmq_recv = false\n\
|
|
rc_zmq_recv_err = error_code__ZMQ_Error__push(rc_zmq_recv)\n\
|
|
else\n\
|
|
rc_zmq_recv = true\n\
|
|
end\n\
|
|
return rc_zmq_recv, rc_zmq_recv_err\n\
|
|
end\n\
|
|
\n\
|
|
local tmp_msg = ffi.new('zmq_msg_t')\n\
|
|
\n\
|
|
-- method: recv\n\
|
|
function ZMQ_Socket_meth.recv(self, flags)\n\
|
|
local this = obj_type_ZMQ_Socket_check(self)\n\
|
|
flags = flags or 0\n\
|
|
local data_len = 0\n\
|
|
local data\n\
|
|
local err\n\
|
|
local msg = tmp_msg\n\
|
|
-- initialize blank message.\n\
|
|
if C.zmq_msg_init(msg) < 0 then\n\
|
|
return nil, get_zmq_strerror()\n\
|
|
end\n\
|
|
\n\
|
|
-- receive message\n\
|
|
err = C.zmq_recv(this, msg, flags)\n\
|
|
if 0 == err then\n\
|
|
local data = ffi.string(C.zmq_msg_data(msg), C.zmq_msg_size(msg))\n\
|
|
-- close message\n\
|
|
C.zmq_msg_close(msg)\n\
|
|
return data\n\
|
|
end\n\
|
|
\n\
|
|
if not (0 ~= err) then\n\
|
|
data = ((nil ~= data) and ffi.string(data,data_len))\n\
|
|
else\n\
|
|
data = nil\n\
|
|
end\n\
|
|
err = error_code__ZMQ_Error__push(err)\n\
|
|
-- close message\n\
|
|
C.zmq_msg_close(msg)\n\
|
|
\n\
|
|
return data, err\n\
|
|
end\n\
|
|
\n\
|
|
-- End \"ZMQ_Socket\" FFI interface\n\
|
|
\n\
|
|
\n\
|
|
-- Start \"ZMQ_Ctx\" FFI interface\n\
|
|
-- method: term\n\
|
|
function ZMQ_Ctx_meth.term(self)\n\
|
|
local this = obj_type_ZMQ_Ctx_check(self)\n\
|
|
local rc_zmq_term\n\
|
|
rc_zmq_term = C.zmq_term(this)\n\
|
|
-- check for error.\n\
|
|
local rc_zmq_term_err\n\
|
|
if (0 ~= rc_zmq_term) then\n\
|
|
rc_zmq_term = false\n\
|
|
rc_zmq_term_err = error_code__ZMQ_Error__push(rc_zmq_term)\n\
|
|
else\n\
|
|
rc_zmq_term = true\n\
|
|
end\n\
|
|
return rc_zmq_term, rc_zmq_term_err\n\
|
|
end\n\
|
|
\n\
|
|
-- method: socket\n\
|
|
function ZMQ_Ctx_meth.socket(self, type)\n\
|
|
local this = obj_type_ZMQ_Ctx_check(self)\n\
|
|
\n\
|
|
local rc_zmq_socket_flags = OBJ_UDATA_FLAG_OWN\n\
|
|
local rc_zmq_socket\n\
|
|
rc_zmq_socket = C.zmq_socket(this, type)\n\
|
|
local rc_zmq_socket_err\n\
|
|
if (nil == rc_zmq_socket) then\n\
|
|
rc_zmq_socket_err = get_zmq_strerror()\n\
|
|
else\n\
|
|
rc_zmq_socket = obj_type_ZMQ_Socket_push(rc_zmq_socket, rc_zmq_socket_flags)\n\
|
|
end\n\
|
|
return rc_zmq_socket, rc_zmq_socket_err\n\
|
|
end\n\
|
|
\n\
|
|
-- End \"ZMQ_Ctx\" FFI interface\n\
|
|
\n\
|
|
-- method: init\n\
|
|
function zmq_meth.init(io_threads)\n\
|
|
\n\
|
|
local rc_zmq_init_flags = OBJ_UDATA_FLAG_OWN\n\
|
|
local rc_zmq_init\n\
|
|
rc_zmq_init = C.zmq_init(io_threads)\n\
|
|
local rc_zmq_init_err\n\
|
|
if (nil == rc_zmq_init) then\n\
|
|
rc_zmq_init_err = get_zmq_strerror()\n\
|
|
else\n\
|
|
rc_zmq_init = obj_type_ZMQ_Ctx_push(rc_zmq_init, rc_zmq_init_flags)\n\
|
|
end\n\
|
|
return rc_zmq_init, rc_zmq_init_err\n\
|
|
end\n\
|
|
\n\
|
|
-- method: device\n\
|
|
function zmq_meth.device(device, insock, outsock)\n\
|
|
\n\
|
|
insock = obj_type_ZMQ_Socket_check(insock)\n\
|
|
outsock = obj_type_ZMQ_Socket_check(outsock)\n\
|
|
local rc_zmq_device\n\
|
|
rc_zmq_device = C.zmq_device(device, insock, outsock)\n\
|
|
-- check for error.\n\
|
|
local rc_zmq_device_err\n\
|
|
if (0 ~= rc_zmq_device) then\n\
|
|
rc_zmq_device = false\n\
|
|
rc_zmq_device_err = error_code__ZMQ_Error__push(rc_zmq_device)\n\
|
|
else\n\
|
|
rc_zmq_device = true\n\
|
|
end\n\
|
|
return rc_zmq_device, rc_zmq_device_err\n\
|
|
end\n\
|
|
\n\
|
|
";
|
|
|
|
/* detect zmq version >= 2.1.0 */
|
|
#define VERSION_2_1 0
|
|
#if defined(ZMQ_VERSION)
|
|
#if (ZMQ_VERSION >= ZMQ_MAKE_VERSION(2,1,0))
|
|
#undef VERSION_2_1
|
|
#define VERSION_2_1 1
|
|
#endif
|
|
#endif
|
|
|
|
typedef void * ZMQ_Socket;
|
|
|
|
#if VERSION_2_1
|
|
#ifdef _WIN32
|
|
#include <winsock2.h>
|
|
typedef SOCKET socket_t;
|
|
#else
|
|
typedef int socket_t;
|
|
#endif
|
|
#endif
|
|
|
|
/* socket option types. */
|
|
#define OPT_TYPE_NONE 0
|
|
#define OPT_TYPE_INT 1
|
|
#define OPT_TYPE_UINT32 2
|
|
#define OPT_TYPE_UINT64 3
|
|
#define OPT_TYPE_INT64 4
|
|
#define OPT_TYPE_STR 5
|
|
#define OPT_TYPE_FD 6
|
|
|
|
static const int opt_types[] = {
|
|
OPT_TYPE_NONE, /* unused */
|
|
OPT_TYPE_UINT64, /* ZMQ_HWM */
|
|
OPT_TYPE_INT64, /* ZMQ_SWAP */
|
|
OPT_TYPE_UINT64, /* ZMQ_AFFINITY */
|
|
OPT_TYPE_STR, /* ZMQ_IDENTITY */
|
|
OPT_TYPE_STR, /* ZMQ_SUBSCRIBE */
|
|
OPT_TYPE_STR, /* ZMQ_UNSUBSCRIBE */
|
|
OPT_TYPE_INT64, /* ZMQ_RATE */
|
|
OPT_TYPE_INT64, /* ZMQ_RECOVERY_IVL */
|
|
OPT_TYPE_INT64, /* ZMQ_MCAST_LOOP */
|
|
OPT_TYPE_UINT64, /* ZMQ_SNDBUF */
|
|
OPT_TYPE_UINT64, /* ZMQ_RCVBUF */
|
|
OPT_TYPE_INT64, /* ZMQ_RCVMORE */
|
|
|
|
#if VERSION_2_1
|
|
OPT_TYPE_FD, /* ZMQ_FD */
|
|
OPT_TYPE_UINT32, /* ZMQ_EVENTS */
|
|
OPT_TYPE_INT, /* ZMQ_TYPE */
|
|
OPT_TYPE_INT, /* ZMQ_LINGER */
|
|
OPT_TYPE_INT, /* ZMQ_RECONNECT_IVL */
|
|
OPT_TYPE_INT, /* ZMQ_BACKLOG */
|
|
#endif
|
|
};
|
|
#define MAX_OPTS ZMQ_BACKLOG
|
|
|
|
|
|
static ZMQ_Error simple_zmq_send(ZMQ_Socket sock, const char *data, size_t data_len, int flags) {
|
|
ZMQ_Error err;
|
|
zmq_msg_t msg;
|
|
/* initialize message */
|
|
err = zmq_msg_init_size(&msg, data_len);
|
|
if(0 == err) {
|
|
/* fill message */
|
|
memcpy(zmq_msg_data(&msg), data, data_len);
|
|
/* send message */
|
|
err = zmq_send(sock, &msg, flags);
|
|
/* close message */
|
|
zmq_msg_close(&msg);
|
|
}
|
|
return err;
|
|
}
|
|
|
|
typedef void * ZMQ_Ctx;
|
|
|
|
#define OBJ_UDATA_CTX_SHOULD_FREE (OBJ_UDATA_LAST_FLAG << 1)
|
|
|
|
/*
|
|
* This wrapper function is to make the EAGAIN/ETERM error messages more like
|
|
* what is returned by LuaSocket.
|
|
*/
|
|
static const char *get_zmq_strerror() {
|
|
int err = zmq_errno();
|
|
switch(err) {
|
|
case EAGAIN:
|
|
return "timeout";
|
|
break;
|
|
case ETERM:
|
|
return "closed";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return zmq_strerror(err);
|
|
}
|
|
|
|
|
|
|
|
|
|
static void error_code__ZMQ_Error__push(lua_State *L, ZMQ_Error err) {
|
|
const char *err_str = NULL;
|
|
if(err != 0) {
|
|
err_str = get_zmq_strerror();
|
|
}
|
|
|
|
if(err_str) {
|
|
lua_pushstring(L, err_str);
|
|
} else {
|
|
lua_pushnil(L);
|
|
}
|
|
}
|
|
|
|
/* method: init */
|
|
static int zmq_msg_t__init__meth(lua_State *L) {
|
|
int this_flags = OBJ_UDATA_FLAG_OWN;
|
|
zmq_msg_t * this;
|
|
ZMQ_Error err = 0;
|
|
zmq_msg_t tmp;
|
|
this = &tmp;
|
|
err = zmq_msg_init(this);
|
|
|
|
if(!(0 != err)) {
|
|
obj_type_zmq_msg_t_push(L, this, this_flags);
|
|
} else {
|
|
lua_pushnil(L);
|
|
}
|
|
error_code__ZMQ_Error__push(L, err);
|
|
return 2;
|
|
}
|
|
|
|
/* method: init_size */
|
|
static int zmq_msg_t__init_size__meth(lua_State *L) {
|
|
size_t size = luaL_checkinteger(L,1);
|
|
int this_flags = OBJ_UDATA_FLAG_OWN;
|
|
zmq_msg_t * this;
|
|
ZMQ_Error err = 0;
|
|
zmq_msg_t tmp;
|
|
this = &tmp;
|
|
err = zmq_msg_init_size(this, size);
|
|
|
|
if(!(0 != err)) {
|
|
obj_type_zmq_msg_t_push(L, this, this_flags);
|
|
} else {
|
|
lua_pushnil(L);
|
|
}
|
|
error_code__ZMQ_Error__push(L, err);
|
|
return 2;
|
|
}
|
|
|
|
/* method: init_data */
|
|
static int zmq_msg_t__init_data__meth(lua_State *L) {
|
|
size_t data_len;
|
|
const char * data = luaL_checklstring(L,1,&(data_len));
|
|
int this_flags = OBJ_UDATA_FLAG_OWN;
|
|
zmq_msg_t * this;
|
|
ZMQ_Error err = 0;
|
|
zmq_msg_t tmp;
|
|
this = &tmp;
|
|
err = zmq_msg_init_size(this, data_len);
|
|
if(0 == err) {
|
|
/* fill message */
|
|
memcpy(zmq_msg_data(this), data, data_len);
|
|
}
|
|
|
|
if(!(0 != err)) {
|
|
obj_type_zmq_msg_t_push(L, this, this_flags);
|
|
} else {
|
|
lua_pushnil(L);
|
|
}
|
|
error_code__ZMQ_Error__push(L, err);
|
|
return 2;
|
|
}
|
|
|
|
/* method: delete */
|
|
static int zmq_msg_t__delete__meth(lua_State *L) {
|
|
int this_flags = 0;
|
|
zmq_msg_t * this = obj_type_zmq_msg_t_delete(L,1,&(this_flags));
|
|
if(!(this_flags & OBJ_UDATA_FLAG_OWN)) { return 0; }
|
|
ZMQ_Error rc_zmq_msg_close = 0;
|
|
rc_zmq_msg_close = zmq_msg_close(this);
|
|
/* check for error. */
|
|
if((0 != rc_zmq_msg_close)) {
|
|
lua_pushboolean(L, 0);
|
|
error_code__ZMQ_Error__push(L, rc_zmq_msg_close);
|
|
} else {
|
|
lua_pushboolean(L, 1);
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
/* method: close */
|
|
static int zmq_msg_t__close__meth(lua_State *L) {
|
|
zmq_msg_t * this = obj_type_zmq_msg_t_check(L,1);
|
|
ZMQ_Error rc_zmq_msg_close = 0;
|
|
rc_zmq_msg_close = zmq_msg_close(this);
|
|
/* check for error. */
|
|
if((0 != rc_zmq_msg_close)) {
|
|
lua_pushboolean(L, 0);
|
|
error_code__ZMQ_Error__push(L, rc_zmq_msg_close);
|
|
} else {
|
|
lua_pushboolean(L, 1);
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
/* method: move */
|
|
static int zmq_msg_t__move__meth(lua_State *L) {
|
|
zmq_msg_t * this = obj_type_zmq_msg_t_check(L,1);
|
|
zmq_msg_t * src = obj_type_zmq_msg_t_check(L,2);
|
|
ZMQ_Error rc_zmq_msg_move = 0;
|
|
rc_zmq_msg_move = zmq_msg_move(this, src);
|
|
/* check for error. */
|
|
if((0 != rc_zmq_msg_move)) {
|
|
lua_pushboolean(L, 0);
|
|
error_code__ZMQ_Error__push(L, rc_zmq_msg_move);
|
|
} else {
|
|
lua_pushboolean(L, 1);
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
/* method: copy */
|
|
static int zmq_msg_t__copy__meth(lua_State *L) {
|
|
zmq_msg_t * this = obj_type_zmq_msg_t_check(L,1);
|
|
zmq_msg_t * src = obj_type_zmq_msg_t_check(L,2);
|
|
ZMQ_Error rc_zmq_msg_copy = 0;
|
|
rc_zmq_msg_copy = zmq_msg_copy(this, src);
|
|
/* check for error. */
|
|
if((0 != rc_zmq_msg_copy)) {
|
|
lua_pushboolean(L, 0);
|
|
error_code__ZMQ_Error__push(L, rc_zmq_msg_copy);
|
|
} else {
|
|
lua_pushboolean(L, 1);
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
/* method: set_data */
|
|
static int zmq_msg_t__set_data__meth(lua_State *L) {
|
|
zmq_msg_t * this = obj_type_zmq_msg_t_check(L,1);
|
|
size_t data_len;
|
|
const char * data = luaL_checklstring(L,2,&(data_len));
|
|
ZMQ_Error err = 0;
|
|
/* check message data size. */
|
|
if(zmq_msg_size(this) != data_len) {
|
|
/* need to resize message. */
|
|
zmq_msg_close(this); /* close old message, to free old data. */
|
|
err = zmq_msg_init_size(this, data_len); /* re-initialize message. */
|
|
if(0 != err) {
|
|
luaL_error(L, "set_data() failed: %s", get_zmq_strerror());
|
|
}
|
|
}
|
|
/* copy data into message */
|
|
memcpy(zmq_msg_data(this), data, data_len);
|
|
|
|
/* check for error. */
|
|
if((0 != err)) {
|
|
lua_pushboolean(L, 0);
|
|
error_code__ZMQ_Error__push(L, err);
|
|
} else {
|
|
lua_pushboolean(L, 1);
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
/* method: data */
|
|
static int zmq_msg_t__data__meth(lua_State *L) {
|
|
zmq_msg_t * this = obj_type_zmq_msg_t_check(L,1);
|
|
void * rc_zmq_msg_data = NULL;
|
|
rc_zmq_msg_data = zmq_msg_data(this);
|
|
lua_pushlightuserdata(L, rc_zmq_msg_data);
|
|
return 1;
|
|
}
|
|
|
|
/* method: set_size */
|
|
static int zmq_msg_t__set_size__meth(lua_State *L) {
|
|
zmq_msg_t * this = obj_type_zmq_msg_t_check(L,1);
|
|
size_t size = luaL_checkinteger(L,2);
|
|
ZMQ_Error err = 0;
|
|
/* check message data size. */
|
|
if(zmq_msg_size(this) != size) {
|
|
/* need to resize message. */
|
|
zmq_msg_close(this); /* close old message, to free old data. */
|
|
err = zmq_msg_init_size(this, size); /* re-initialize message. */
|
|
if(0 != err) {
|
|
luaL_error(L, "set_size() failed: %s", get_zmq_strerror());
|
|
}
|
|
}
|
|
|
|
/* check for error. */
|
|
if((0 != err)) {
|
|
lua_pushboolean(L, 0);
|
|
error_code__ZMQ_Error__push(L, err);
|
|
} else {
|
|
lua_pushboolean(L, 1);
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
/* method: size */
|
|
static int zmq_msg_t__size__meth(lua_State *L) {
|
|
zmq_msg_t * this = obj_type_zmq_msg_t_check(L,1);
|
|
size_t rc_zmq_msg_size = 0;
|
|
rc_zmq_msg_size = zmq_msg_size(this);
|
|
lua_pushinteger(L, rc_zmq_msg_size);
|
|
return 1;
|
|
}
|
|
|
|
/* method: __tostring */
|
|
static int zmq_msg_t____tostring__meth(lua_State *L) {
|
|
zmq_msg_t * this = obj_type_zmq_msg_t_check(L,1);
|
|
size_t data_len = 0;
|
|
const char * data = NULL;
|
|
data = zmq_msg_data(this);
|
|
data_len = zmq_msg_size(this);
|
|
|
|
if(data == NULL) lua_pushnil(L); else lua_pushlstring(L, data,data_len);
|
|
return 1;
|
|
}
|
|
|
|
/* method: close */
|
|
static int ZMQ_Socket__close__meth(lua_State *L) {
|
|
int this_flags = 0;
|
|
ZMQ_Socket * this = obj_type_ZMQ_Socket_delete(L,1,&(this_flags));
|
|
if(!(this_flags & OBJ_UDATA_FLAG_OWN)) { return 0; }
|
|
ZMQ_Error rc_zmq_close = 0;
|
|
rc_zmq_close = zmq_close(this);
|
|
/* check for error. */
|
|
if((0 != rc_zmq_close)) {
|
|
lua_pushboolean(L, 0);
|
|
error_code__ZMQ_Error__push(L, rc_zmq_close);
|
|
} else {
|
|
lua_pushboolean(L, 1);
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
/* method: bind */
|
|
static int ZMQ_Socket__bind__meth(lua_State *L) {
|
|
ZMQ_Socket * this = obj_type_ZMQ_Socket_check(L,1);
|
|
size_t addr_len;
|
|
const char * addr = luaL_checklstring(L,2,&(addr_len));
|
|
ZMQ_Error rc_zmq_bind = 0;
|
|
rc_zmq_bind = zmq_bind(this, addr);
|
|
/* check for error. */
|
|
if((0 != rc_zmq_bind)) {
|
|
lua_pushboolean(L, 0);
|
|
error_code__ZMQ_Error__push(L, rc_zmq_bind);
|
|
} else {
|
|
lua_pushboolean(L, 1);
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
/* method: connect */
|
|
static int ZMQ_Socket__connect__meth(lua_State *L) {
|
|
ZMQ_Socket * this = obj_type_ZMQ_Socket_check(L,1);
|
|
size_t addr_len;
|
|
const char * addr = luaL_checklstring(L,2,&(addr_len));
|
|
ZMQ_Error rc_zmq_connect = 0;
|
|
rc_zmq_connect = zmq_connect(this, addr);
|
|
/* check for error. */
|
|
if((0 != rc_zmq_connect)) {
|
|
lua_pushboolean(L, 0);
|
|
error_code__ZMQ_Error__push(L, rc_zmq_connect);
|
|
} else {
|
|
lua_pushboolean(L, 1);
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
/* method: setopt */
|
|
static int ZMQ_Socket__setopt__meth(lua_State *L) {
|
|
ZMQ_Socket * this = obj_type_ZMQ_Socket_check(L,1);
|
|
uint32_t opt = luaL_checkinteger(L,2);
|
|
ZMQ_Error err = 0;
|
|
size_t val_len;
|
|
const void *val;
|
|
|
|
socket_t fd_val;
|
|
int int_val;
|
|
uint32_t uint32_val;
|
|
uint64_t uint64_val;
|
|
int64_t int64_val;
|
|
|
|
if(opt > MAX_OPTS) {
|
|
return luaL_argerror(L, 2, "Invalid socket option.");
|
|
}
|
|
|
|
switch(opt_types[opt]) {
|
|
case OPT_TYPE_FD:
|
|
fd_val = luaL_checklong(L, 3);
|
|
val = &fd_val;
|
|
val_len = sizeof(fd_val);
|
|
break;
|
|
case OPT_TYPE_INT:
|
|
int_val = luaL_checklong(L, 3);
|
|
val = &int_val;
|
|
val_len = sizeof(int_val);
|
|
break;
|
|
case OPT_TYPE_UINT32:
|
|
uint32_val = luaL_checklong(L, 3);
|
|
val = &uint32_val;
|
|
val_len = sizeof(uint32_val);
|
|
break;
|
|
case OPT_TYPE_UINT64:
|
|
uint64_val = luaL_checklong(L, 3);
|
|
val = &uint64_val;
|
|
val_len = sizeof(uint64_val);
|
|
break;
|
|
case OPT_TYPE_INT64:
|
|
int64_val = luaL_checklong(L, 3);
|
|
val = &int64_val;
|
|
val_len = sizeof(int64_val);
|
|
break;
|
|
case OPT_TYPE_STR:
|
|
val = luaL_checklstring(L, 3, &(val_len));
|
|
break;
|
|
default:
|
|
printf("Invalid socket option type, this shouldn't happen.\n");
|
|
abort();
|
|
break;
|
|
}
|
|
err = zmq_setsockopt(this, opt, val, val_len);
|
|
|
|
/* check for error. */
|
|
if((0 != err)) {
|
|
lua_pushboolean(L, 0);
|
|
error_code__ZMQ_Error__push(L, err);
|
|
} else {
|
|
lua_pushboolean(L, 1);
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
/* method: getopt */
|
|
static int ZMQ_Socket__getopt__meth(lua_State *L) {
|
|
ZMQ_Socket * this = obj_type_ZMQ_Socket_check(L,1);
|
|
uint32_t opt = luaL_checkinteger(L,2);
|
|
ZMQ_Error err = 0;
|
|
size_t val_len;
|
|
|
|
socket_t fd_val;
|
|
int int_val;
|
|
uint32_t uint32_val;
|
|
uint64_t uint64_val;
|
|
int64_t int64_val;
|
|
#define STR_MAX 255
|
|
char str_val[STR_MAX];
|
|
|
|
if(opt > MAX_OPTS) {
|
|
lua_pushnil(L);
|
|
lua_pushliteral(L, "Invalid socket option.");
|
|
return 2;
|
|
}
|
|
|
|
switch(opt_types[opt]) {
|
|
case OPT_TYPE_FD:
|
|
val_len = sizeof(fd_val);
|
|
err = zmq_getsockopt(this, opt, &fd_val, &val_len);
|
|
if(0 == err) {
|
|
lua_pushinteger(L, (lua_Integer)fd_val);
|
|
return 1;
|
|
}
|
|
break;
|
|
case OPT_TYPE_INT:
|
|
val_len = sizeof(int_val);
|
|
err = zmq_getsockopt(this, opt, &int_val, &val_len);
|
|
if(0 == err) {
|
|
lua_pushinteger(L, (lua_Integer)int_val);
|
|
return 1;
|
|
}
|
|
break;
|
|
case OPT_TYPE_UINT32:
|
|
val_len = sizeof(uint32_val);
|
|
err = zmq_getsockopt(this, opt, &uint32_val, &val_len);
|
|
if(0 == err) {
|
|
lua_pushinteger(L, (lua_Integer)uint32_val);
|
|
return 1;
|
|
}
|
|
break;
|
|
case OPT_TYPE_UINT64:
|
|
val_len = sizeof(uint64_val);
|
|
err = zmq_getsockopt(this, opt, &uint64_val, &val_len);
|
|
if(0 == err) {
|
|
lua_pushinteger(L, (lua_Integer)uint64_val);
|
|
return 1;
|
|
}
|
|
break;
|
|
case OPT_TYPE_INT64:
|
|
val_len = sizeof(int64_val);
|
|
err = zmq_getsockopt(this, opt, &int64_val, &val_len);
|
|
if(0 == err) {
|
|
lua_pushinteger(L, (lua_Integer)int64_val);
|
|
return 1;
|
|
}
|
|
break;
|
|
case OPT_TYPE_STR:
|
|
val_len = STR_MAX;
|
|
err = zmq_getsockopt(this, opt, str_val, &val_len);
|
|
if(0 == err) {
|
|
lua_pushlstring(L, str_val, val_len);
|
|
return 1;
|
|
}
|
|
#undef STR_MAX
|
|
break;
|
|
default:
|
|
printf("Invalid socket option type, this shouldn't happen.\n");
|
|
abort();
|
|
break;
|
|
}
|
|
lua_pushnil(L);
|
|
|
|
error_code__ZMQ_Error__push(L, err);
|
|
return 2;
|
|
}
|
|
|
|
/* method: events */
|
|
static int ZMQ_Socket__events__meth(lua_State *L) {
|
|
ZMQ_Socket * this = obj_type_ZMQ_Socket_check(L,1);
|
|
uint32_t events = 0;
|
|
ZMQ_Error err = 0;
|
|
size_t val_len = sizeof(events);
|
|
err = zmq_getsockopt(this, ZMQ_EVENTS, &(events), &val_len);
|
|
|
|
if(!(0 != err)) {
|
|
lua_pushinteger(L, events);
|
|
} else {
|
|
lua_pushnil(L);
|
|
}
|
|
error_code__ZMQ_Error__push(L, err);
|
|
return 2;
|
|
}
|
|
|
|
/* method: send_msg */
|
|
static int ZMQ_Socket__send_msg__meth(lua_State *L) {
|
|
ZMQ_Socket * this = obj_type_ZMQ_Socket_check(L,1);
|
|
zmq_msg_t * msg = obj_type_zmq_msg_t_check(L,2);
|
|
int flags = luaL_optinteger(L,3,0);
|
|
ZMQ_Error rc_zmq_send = 0;
|
|
rc_zmq_send = zmq_send(this, msg, flags);
|
|
/* check for error. */
|
|
if((0 != rc_zmq_send)) {
|
|
lua_pushboolean(L, 0);
|
|
error_code__ZMQ_Error__push(L, rc_zmq_send);
|
|
} else {
|
|
lua_pushboolean(L, 1);
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
/* method: send */
|
|
static int ZMQ_Socket__send__meth(lua_State *L) {
|
|
ZMQ_Socket * this = obj_type_ZMQ_Socket_check(L,1);
|
|
size_t data_len;
|
|
const char * data = luaL_checklstring(L,2,&(data_len));
|
|
int flags = luaL_optinteger(L,3,0);
|
|
ZMQ_Error err = 0;
|
|
err = simple_zmq_send(this, data, data_len, flags);
|
|
|
|
/* check for error. */
|
|
if((0 != err)) {
|
|
lua_pushboolean(L, 0);
|
|
error_code__ZMQ_Error__push(L, err);
|
|
} else {
|
|
lua_pushboolean(L, 1);
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
/* method: recv_msg */
|
|
static int ZMQ_Socket__recv_msg__meth(lua_State *L) {
|
|
ZMQ_Socket * this = obj_type_ZMQ_Socket_check(L,1);
|
|
zmq_msg_t * msg = obj_type_zmq_msg_t_check(L,2);
|
|
int flags = luaL_optinteger(L,3,0);
|
|
ZMQ_Error rc_zmq_recv = 0;
|
|
rc_zmq_recv = zmq_recv(this, msg, flags);
|
|
/* check for error. */
|
|
if((0 != rc_zmq_recv)) {
|
|
lua_pushboolean(L, 0);
|
|
error_code__ZMQ_Error__push(L, rc_zmq_recv);
|
|
} else {
|
|
lua_pushboolean(L, 1);
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
/* method: recv */
|
|
static int ZMQ_Socket__recv__meth(lua_State *L) {
|
|
ZMQ_Socket * this = obj_type_ZMQ_Socket_check(L,1);
|
|
int flags = luaL_optinteger(L,2,0);
|
|
size_t data_len = 0;
|
|
const char * data = NULL;
|
|
ZMQ_Error err = 0;
|
|
zmq_msg_t msg;
|
|
/* initialize message */
|
|
err = zmq_msg_init(&msg);
|
|
if(0 == err) {
|
|
/* receive message */
|
|
err = zmq_recv(this, &msg, flags);
|
|
if(0 == err) {
|
|
data = zmq_msg_data(&msg);
|
|
data_len = zmq_msg_size(&msg);
|
|
}
|
|
}
|
|
|
|
if(!(0 != err)) {
|
|
if(data == NULL) lua_pushnil(L); else lua_pushlstring(L, data,data_len);
|
|
} else {
|
|
lua_pushnil(L);
|
|
}
|
|
error_code__ZMQ_Error__push(L, err);
|
|
/* close message */
|
|
zmq_msg_close(&msg);
|
|
|
|
return 2;
|
|
}
|
|
|
|
/* method: delete */
|
|
static int ZMQ_Ctx__delete__meth(lua_State *L) {
|
|
int this_flags = 0;
|
|
ZMQ_Ctx * this = obj_type_ZMQ_Ctx_delete(L,1,&(this_flags));
|
|
if(!(this_flags & OBJ_UDATA_FLAG_OWN)) { return 0; }
|
|
if(this_flags & OBJ_UDATA_CTX_SHOULD_FREE) {
|
|
zmq_term(this);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* method: term */
|
|
static int ZMQ_Ctx__term__meth(lua_State *L) {
|
|
ZMQ_Ctx * this = obj_type_ZMQ_Ctx_check(L,1);
|
|
ZMQ_Error rc_zmq_term = 0;
|
|
rc_zmq_term = zmq_term(this);
|
|
/* check for error. */
|
|
if((0 != rc_zmq_term)) {
|
|
lua_pushboolean(L, 0);
|
|
error_code__ZMQ_Error__push(L, rc_zmq_term);
|
|
} else {
|
|
lua_pushboolean(L, 1);
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
/* method: lightuserdata */
|
|
static int ZMQ_Ctx__lightuserdata__meth(lua_State *L) {
|
|
ZMQ_Ctx * this = obj_type_ZMQ_Ctx_check(L,1);
|
|
void * ptr = NULL;
|
|
ptr = this;
|
|
|
|
lua_pushlightuserdata(L, ptr);
|
|
return 1;
|
|
}
|
|
|
|
/* method: socket */
|
|
static int ZMQ_Ctx__socket__meth(lua_State *L) {
|
|
ZMQ_Ctx * this = obj_type_ZMQ_Ctx_check(L,1);
|
|
int type = luaL_checkinteger(L,2);
|
|
int rc_zmq_socket_flags = OBJ_UDATA_FLAG_OWN;
|
|
ZMQ_Socket rc_zmq_socket;
|
|
rc_zmq_socket = zmq_socket(this, type);
|
|
if((NULL == rc_zmq_socket)) {
|
|
lua_pushnil(L);
|
|
lua_pushstring(L, get_zmq_strerror());
|
|
} else {
|
|
obj_type_ZMQ_Socket_push(L, rc_zmq_socket, rc_zmq_socket_flags);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* method: version */
|
|
static int zmq__version__func(lua_State *L) {
|
|
int major, minor, patch;
|
|
zmq_version(&(major), &(minor), &(patch));
|
|
|
|
/* return version as a table: { major, minor, patch } */
|
|
lua_createtable(L, 3, 0);
|
|
lua_pushinteger(L, major);
|
|
lua_rawseti(L, -2, 1);
|
|
lua_pushinteger(L, minor);
|
|
lua_rawseti(L, -2, 2);
|
|
lua_pushinteger(L, patch);
|
|
lua_rawseti(L, -2, 3);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* method: init */
|
|
static int zmq__init__func(lua_State *L) {
|
|
int io_threads = luaL_checkinteger(L,1);
|
|
int rc_zmq_init_flags = OBJ_UDATA_FLAG_OWN;
|
|
ZMQ_Ctx rc_zmq_init;
|
|
rc_zmq_init = zmq_init(io_threads);
|
|
if((NULL == rc_zmq_init)) {
|
|
lua_pushnil(L);
|
|
lua_pushstring(L, get_zmq_strerror());
|
|
} else {
|
|
obj_type_ZMQ_Ctx_push(L, rc_zmq_init, rc_zmq_init_flags);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* method: init_ctx */
|
|
static int zmq__init_ctx__func(lua_State *L) {
|
|
int ctx_flags = OBJ_UDATA_FLAG_OWN;
|
|
ZMQ_Ctx ctx;
|
|
if(lua_isuserdata(L, 1)) {
|
|
ctx = lua_touserdata(L, 1);
|
|
} else {
|
|
/* check if value is a LuaJIT 'cdata' */
|
|
int type = lua_type(L, 1);
|
|
const char *typename = lua_typename(L, type);
|
|
if(strncmp(typename, "cdata", sizeof("cdata")) == 0) {
|
|
ctx = (void *)lua_topointer(L, 1);
|
|
} else {
|
|
return luaL_argerror(L, 1, "(expected userdata)");
|
|
}
|
|
}
|
|
|
|
if((NULL == ctx)) {
|
|
lua_pushnil(L);
|
|
lua_pushstring(L, get_zmq_strerror());
|
|
} else {
|
|
obj_type_ZMQ_Ctx_push(L, ctx, ctx_flags);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* method: device */
|
|
static int zmq__device__func(lua_State *L) {
|
|
int device = luaL_checkinteger(L,1);
|
|
ZMQ_Socket insock = obj_type_ZMQ_Socket_check(L,2);
|
|
ZMQ_Socket outsock = obj_type_ZMQ_Socket_check(L,3);
|
|
ZMQ_Error rc_zmq_device = 0;
|
|
rc_zmq_device = zmq_device(device, insock, outsock);
|
|
/* check for error. */
|
|
if((0 != rc_zmq_device)) {
|
|
lua_pushboolean(L, 0);
|
|
error_code__ZMQ_Error__push(L, rc_zmq_device);
|
|
} else {
|
|
lua_pushboolean(L, 1);
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
/* method: dump_ffi */
|
|
static int zmq__dump_ffi__func(lua_State *L) {
|
|
size_t ffi_code_len = 0;
|
|
const char * ffi_code = NULL;
|
|
ffi_code = zmq_ffi_lua_code;
|
|
ffi_code_len = sizeof(zmq_ffi_lua_code) - 1;
|
|
|
|
if(ffi_code == NULL) lua_pushnil(L); else lua_pushlstring(L, ffi_code,ffi_code_len);
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
static const luaL_reg obj_zmq_msg_t_pub_funcs[] = {
|
|
{"init", zmq_msg_t__init__meth},
|
|
{"init_size", zmq_msg_t__init_size__meth},
|
|
{"init_data", zmq_msg_t__init_data__meth},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const luaL_reg obj_zmq_msg_t_methods[] = {
|
|
{"close", zmq_msg_t__close__meth},
|
|
{"move", zmq_msg_t__move__meth},
|
|
{"copy", zmq_msg_t__copy__meth},
|
|
{"set_data", zmq_msg_t__set_data__meth},
|
|
{"data", zmq_msg_t__data__meth},
|
|
{"set_size", zmq_msg_t__set_size__meth},
|
|
{"size", zmq_msg_t__size__meth},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const luaL_reg obj_zmq_msg_t_metas[] = {
|
|
{"__gc", zmq_msg_t__delete__meth},
|
|
{"__tostring", zmq_msg_t____tostring__meth},
|
|
{"__eq", obj_simple_udata_default_equal},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const obj_base obj_zmq_msg_t_bases[] = {
|
|
{-1, NULL}
|
|
};
|
|
|
|
static const obj_field obj_zmq_msg_t_fields[] = {
|
|
{NULL, 0, 0, 0}
|
|
};
|
|
|
|
static const obj_const obj_zmq_msg_t_constants[] = {
|
|
{NULL, NULL, 0.0 , 0}
|
|
};
|
|
|
|
static const luaL_reg obj_ZMQ_Socket_pub_funcs[] = {
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const luaL_reg obj_ZMQ_Socket_methods[] = {
|
|
{"close", ZMQ_Socket__close__meth},
|
|
{"bind", ZMQ_Socket__bind__meth},
|
|
{"connect", ZMQ_Socket__connect__meth},
|
|
{"setopt", ZMQ_Socket__setopt__meth},
|
|
{"getopt", ZMQ_Socket__getopt__meth},
|
|
{"events", ZMQ_Socket__events__meth},
|
|
{"send_msg", ZMQ_Socket__send_msg__meth},
|
|
{"send", ZMQ_Socket__send__meth},
|
|
{"recv_msg", ZMQ_Socket__recv_msg__meth},
|
|
{"recv", ZMQ_Socket__recv__meth},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const luaL_reg obj_ZMQ_Socket_metas[] = {
|
|
{"__gc", ZMQ_Socket__close__meth},
|
|
{"__tostring", obj_udata_default_tostring},
|
|
{"__eq", obj_udata_default_equal},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const obj_base obj_ZMQ_Socket_bases[] = {
|
|
{-1, NULL}
|
|
};
|
|
|
|
static const obj_field obj_ZMQ_Socket_fields[] = {
|
|
{NULL, 0, 0, 0}
|
|
};
|
|
|
|
static const obj_const obj_ZMQ_Socket_constants[] = {
|
|
{NULL, NULL, 0.0 , 0}
|
|
};
|
|
|
|
static const luaL_reg obj_ZMQ_Ctx_pub_funcs[] = {
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const luaL_reg obj_ZMQ_Ctx_methods[] = {
|
|
{"term", ZMQ_Ctx__term__meth},
|
|
{"lightuserdata", ZMQ_Ctx__lightuserdata__meth},
|
|
{"socket", ZMQ_Ctx__socket__meth},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const luaL_reg obj_ZMQ_Ctx_metas[] = {
|
|
{"__gc", ZMQ_Ctx__delete__meth},
|
|
{"__tostring", obj_udata_default_tostring},
|
|
{"__eq", obj_udata_default_equal},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const obj_base obj_ZMQ_Ctx_bases[] = {
|
|
{-1, NULL}
|
|
};
|
|
|
|
static const obj_field obj_ZMQ_Ctx_fields[] = {
|
|
{NULL, 0, 0, 0}
|
|
};
|
|
|
|
static const obj_const obj_ZMQ_Ctx_constants[] = {
|
|
{NULL, NULL, 0.0 , 0}
|
|
};
|
|
|
|
static const luaL_reg zmq_function[] = {
|
|
{"version", zmq__version__func},
|
|
{"init", zmq__init__func},
|
|
{"init_ctx", zmq__init_ctx__func},
|
|
{"device", zmq__device__func},
|
|
{"dump_ffi", zmq__dump_ffi__func},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const obj_const zmq_constants[] = {
|
|
{"TYPE", NULL, 16, CONST_NUMBER},
|
|
{"RCVMORE", NULL, 13, CONST_NUMBER},
|
|
{"LINGER", NULL, 17, CONST_NUMBER},
|
|
{"SWAP", NULL, 3, CONST_NUMBER},
|
|
{"MSG_SHARED", NULL, 128, CONST_NUMBER},
|
|
{"SNDBUF", NULL, 11, CONST_NUMBER},
|
|
{"STREAMER", NULL, 1, CONST_NUMBER},
|
|
{"NOBLOCK", NULL, 1, CONST_NUMBER},
|
|
{"RCVBUF", NULL, 12, CONST_NUMBER},
|
|
{"FORWARDER", NULL, 2, CONST_NUMBER},
|
|
{"RATE", NULL, 8, CONST_NUMBER},
|
|
{"IDENTITY", NULL, 5, CONST_NUMBER},
|
|
{"SUB", NULL, 2, CONST_NUMBER},
|
|
{"FD", NULL, 14, CONST_NUMBER},
|
|
{"PUB", NULL, 1, CONST_NUMBER},
|
|
{"DELIMITER", NULL, 31, CONST_NUMBER},
|
|
{"BACKLOG", NULL, 19, CONST_NUMBER},
|
|
{"SNDMORE", NULL, 2, CONST_NUMBER},
|
|
{"POLLIN", NULL, 1, CONST_NUMBER},
|
|
{"REP", NULL, 4, CONST_NUMBER},
|
|
{"POLLERR", NULL, 4, CONST_NUMBER},
|
|
{"MAX_VSM_SIZE", NULL, 30, CONST_NUMBER},
|
|
{"PUSH", NULL, 8, CONST_NUMBER},
|
|
{"HWM", NULL, 1, CONST_NUMBER},
|
|
{"MSG_MORE", NULL, 1, CONST_NUMBER},
|
|
{"REQ", NULL, 3, CONST_NUMBER},
|
|
{"UNSUBSCRIBE", NULL, 7, CONST_NUMBER},
|
|
{"PULL", NULL, 7, CONST_NUMBER},
|
|
{"PAIR", NULL, 0, CONST_NUMBER},
|
|
{"QUEUE", NULL, 3, CONST_NUMBER},
|
|
{"EVENTS", NULL, 15, CONST_NUMBER},
|
|
{"XREQ", NULL, 5, CONST_NUMBER},
|
|
{"XREP", NULL, 6, CONST_NUMBER},
|
|
{"SUBSCRIBE", NULL, 6, CONST_NUMBER},
|
|
{"MCAST_LOOP", NULL, 10, CONST_NUMBER},
|
|
{"VSM", NULL, 32, CONST_NUMBER},
|
|
{"RECOVERY_IVL", NULL, 9, CONST_NUMBER},
|
|
{"RECONNECT_IVL", NULL, 18, CONST_NUMBER},
|
|
{"POLLOUT", NULL, 2, CONST_NUMBER},
|
|
{"AFFINITY", NULL, 4, CONST_NUMBER},
|
|
{NULL, NULL, 0.0 , 0}
|
|
};
|
|
|
|
static const ffi_export_symbol zmq_ffi_export[] = {
|
|
{ "get_zmq_strerror", get_zmq_strerror },
|
|
{ "simple_zmq_send", simple_zmq_send },
|
|
{NULL, NULL}
|
|
};
|
|
|
|
|
|
|
|
static const reg_sub_module reg_sub_modules[] = {
|
|
{ &(obj_type_zmq_msg_t), 0, obj_zmq_msg_t_pub_funcs, obj_zmq_msg_t_methods, obj_zmq_msg_t_metas, obj_zmq_msg_t_bases, obj_zmq_msg_t_fields, obj_zmq_msg_t_constants},
|
|
{ &(obj_type_ZMQ_Socket), 0, obj_ZMQ_Socket_pub_funcs, obj_ZMQ_Socket_methods, obj_ZMQ_Socket_metas, obj_ZMQ_Socket_bases, obj_ZMQ_Socket_fields, obj_ZMQ_Socket_constants},
|
|
{ &(obj_type_ZMQ_Ctx), 0, obj_ZMQ_Ctx_pub_funcs, obj_ZMQ_Ctx_methods, obj_ZMQ_Ctx_metas, obj_ZMQ_Ctx_bases, obj_ZMQ_Ctx_fields, obj_ZMQ_Ctx_constants},
|
|
{NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL}
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const luaL_Reg submodule_libs[] = {
|
|
{NULL, NULL}
|
|
};
|
|
|
|
|
|
|
|
static void create_object_instance_cache(lua_State *L) {
|
|
lua_pushlightuserdata(L, obj_udata_weak_ref_key); /* key for weak table. */
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* check if weak table exists already. */
|
|
if(!lua_isnil(L, -1)) {
|
|
lua_pop(L, 1); /* pop weak table. */
|
|
return;
|
|
}
|
|
lua_pop(L, 1); /* pop nil. */
|
|
/* create weak table for object instance references. */
|
|
lua_pushlightuserdata(L, obj_udata_weak_ref_key); /* key for weak table. */
|
|
lua_newtable(L); /* weak table. */
|
|
lua_newtable(L); /* metatable for weak table. */
|
|
lua_pushliteral(L, "__mode");
|
|
lua_pushliteral(L, "v");
|
|
lua_rawset(L, -3); /* metatable.__mode = 'v' weak values. */
|
|
lua_setmetatable(L, -2); /* add metatable to weak table. */
|
|
lua_rawset(L, LUA_REGISTRYINDEX); /* create reference to weak table. */
|
|
}
|
|
|
|
int luaopen_zmq(lua_State *L) {
|
|
const reg_sub_module *reg = reg_sub_modules;
|
|
const luaL_Reg *submodules = submodule_libs;
|
|
int priv_table = -1;
|
|
|
|
#if LUAJIT_FFI
|
|
/* private table to hold reference to object metatables. */
|
|
lua_newtable(L);
|
|
priv_table = lua_gettop(L);
|
|
#endif
|
|
|
|
/* create object cache. */
|
|
create_object_instance_cache(L);
|
|
|
|
/* module table. */
|
|
luaL_register(L, "zmq", zmq_function);
|
|
|
|
/* register module constants. */
|
|
obj_type_register_constants(L, zmq_constants, -1);
|
|
|
|
for(; submodules->func != NULL ; submodules++) {
|
|
lua_pushcfunction(L, submodules->func);
|
|
lua_pushstring(L, submodules->name);
|
|
lua_call(L, 1, 0);
|
|
}
|
|
|
|
/* register objects */
|
|
for(; reg->type != NULL ; reg++) {
|
|
lua_newtable(L); /* create public API table for object. */
|
|
lua_pushvalue(L, -1); /* dup. object's public API table. */
|
|
lua_setfield(L, -3, reg->type->name); /* module["<object_name>"] = <object public API> */
|
|
#if REG_OBJECTS_AS_GLOBALS
|
|
lua_pushvalue(L, -1); /* dup value. */
|
|
lua_setglobal(L, reg->type->name); /* global: <object_name> = <object public API> */
|
|
#endif
|
|
obj_type_register(L, reg, priv_table);
|
|
}
|
|
|
|
#if LUAJIT_FFI
|
|
nobj_try_loading_ffi(L, "zmq", zmq_ffi_lua_code,
|
|
zmq_ffi_export, priv_table);
|
|
#endif
|
|
return 1;
|
|
}
|
|
|
|
|