static ERL_NIF_TERM _listener (ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { CAN_handle* handle; ErlNifPid pid = { 0 }; // NOTE: breaking opaque type! enif_get_resource(env, argv[0], CAN_handle_type, (void**) &handle); if (handle->threaded) // there is a thread already and some pid! { pid = handle->receiver; } if (!enif_get_local_pid(env, argv[1], &handle->receiver)) // NOTE: use lock if pid type is structural! { handle->threaded = 0; return enif_make_badarg(env); } else { enif_get_uint(env, argv[2], &handle->chunk_size); enif_get_long(env, argv[3], &handle->timeout); if (!handle->threaded) // a thread was not created already { if (enif_thread_create("can_reading_thread", &handle->tid, _reading_thread, handle, 0)) { handle->threaded = 0; return enif_make_int(env, -1004); } } } return pid.pid ? enif_make_pid(env, &pid) : enif_make_int(env, 0); }
static ERL_NIF_TERM send_from_dirty_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM result; ErlNifPid pid; int res; if (!enif_get_local_pid(env, argv[0], &pid)) return enif_make_badarg(env); result = enif_make_tuple2(env, enif_make_atom(env, "ok"), enif_make_pid(env, &pid)); res = enif_send(env, &pid, NULL, result); if (!res) return enif_make_badarg(env); else return result; }
static int whereis_lookup_term( ErlNifEnv* env, int type, ERL_NIF_TERM name, ERL_NIF_TERM* out) { whereis_term_data_t res; int rc = whereis_lookup_internal(env, type, name, &res); if (rc == WHEREIS_SUCCESS) { switch (type) { case WHEREIS_LOOKUP_PID: *out = enif_make_pid(env, & res.pid); break; case WHEREIS_LOOKUP_PORT: *out = enif_make_port(env, & res.port); break; default: rc = WHEREIS_ERROR_TYPE; break; } } return rc; }
static ERL_NIF_TERM dirty_call_while_terminated_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifPid self; ERL_NIF_TERM result, self_term; ErlNifPid to; ErlNifEnv* menv; int res; if (!enif_get_local_pid(env, argv[0], &to)) return enif_make_badarg(env); if (!enif_self(env, &self)) return enif_make_badarg(env); self_term = enif_make_pid(env, &self); menv = enif_alloc_env(); result = enif_make_tuple2(menv, enif_make_atom(menv, "dirty_alive"), self_term); res = enif_send(env, &to, menv, result); enif_free_env(menv); if (!res) return enif_make_badarg(env); /* Wait until we have been killed */ while (enif_is_process_alive(env, &self)) ; result = enif_make_tuple2(env, enif_make_atom(env, "dirty_dead"), self_term); res = enif_send(env, &to, NULL, result); #ifdef __WIN32__ Sleep(1000); #else sleep(1); #endif return enif_make_atom(env, "ok"); }
static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { int state_arity; ErlNifPid self, to; ERL_NIF_TERM *tuple, msg; ASSERT(argc == 5); tuple = enif_alloc(sizeof(ERL_NIF_TERM)*(argc+1)); memcpy(tuple+1,argv,sizeof(ERL_NIF_TERM)*argc); if (enif_self(env, &self)) { tuple[0] = enif_make_pid(env, &self); } else { tuple[0] = enif_make_atom(env, "undefined"); } msg = enif_make_tuple_from_array(env, tuple, argc + 1); enif_get_local_pid(env, argv[1], &to); enif_send(env, &to, NULL, msg); enif_free(tuple); return atom_ok; }
static ERL_NIF_TERM GetPid(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { TRACE("GetPid\n"); return enif_make_pid(env, &server); }
// takes the first term off of the lua stack and return it as an // erlang term in the state 'env'. static int terminator_toerl_core(lua_State* lua, ERL_NIF_TERM *result, ErlNifEnv* env, ErlNifResourceType* resource_type) { const int top = lua_gettop(lua); switch(lua_type(lua, top)) { case LUA_TNIL: { *result = enif_make_atom(env, "nil"); lua_pop( lua, 1); assert(lua_gettop(lua) == top-1); return 1; break; } case LUA_TNUMBER: { const lua_Number number = luaL_checknumber(lua, top); if(is_int64(number)) { *result = enif_make_int64(env, (int64_t)number); } else { *result = enif_make_double(env, (double)number); } lua_pop( lua, 1); assert(lua_gettop(lua) == top-1); return 1; break; } case LUA_TBOOLEAN: { const int truefalse = lua_toboolean(lua, top); *result = truefalse ? enif_make_atom(env, "true") : enif_make_atom(env, "false"); lua_pop( lua, 1); assert(lua_gettop(lua) == top-1); return 1; break; } case LUA_TSTRING: { // get the lua string size_t string_len; const char * lua_string = lua_tolstring (lua, top, &string_len); // make space in erlang for it ErlNifBinary binary; if(enif_alloc_binary(string_len, &binary)) { // clean it memset(binary.data, 0, binary.size); // copy it over memcpy(binary.data, lua_string, string_len); *result = enif_make_binary(env, &binary); } else { luaL_error (lua, "could not convert lua string"); } lua_pop( lua, 1); assert(lua_gettop(lua) == top-1); return 1; break; } case LUA_TTABLE: { size_t table_size = 0; int is_array = lua_is_array(lua); // table is at the top of the stack lua_pushnil(lua); // nil as the first key while (lua_next(lua, top) != 0) { ++table_size; lua_pop(lua, 1); } // make sure we can grow the stack luaL_checkstack(lua, 2, ERROR_STACK_MESSAGE); ERL_NIF_TERM *new_table = (ERL_NIF_TERM*) node_alloc(table_size * sizeof(ERL_NIF_TERM)); ERL_NIF_TERM *next_cell = new_table; // table is at the top of the stack lua_pushnil(lua); // nil as the first key while (lua_next(lua, top) != 0) { // uses 'key' (at index -2) and 'value' (at index -1) if(is_array) { // remove 'value', keeps 'key' for next iteration ERL_NIF_TERM value; terminator_toerl_core(lua, &value, env, resource_type); *next_cell = value; } else { // remove 'value', keeps 'key' for next iteration ERL_NIF_TERM tuple_value; terminator_toerl_core(lua, &tuple_value, env, resource_type); ERL_NIF_TERM tuple_key; lua_pushvalue( lua, -1); terminator_toerl_core(lua, &tuple_key, env, resource_type); *next_cell = enif_make_tuple2(env, tuple_key, tuple_value); } next_cell++; } if(NULL != new_table) { *result = enif_make_list_from_array(env, new_table, table_size); node_free(new_table); } lua_pop( lua, 1); assert(lua_gettop(lua) == top-1); return 1; break; } case LUA_TUSERDATA: { // add metatable to stack if(lua_getmetatable (lua, top)) { // put the pid metatable onto the stack // compare the two metatables luaL_getmetatable(lua, TYPE_ERL_PID); if(lua_compare(lua, -1, -2, LUA_OPEQ)) { const ErlNifPid* userdata = (const ErlNifPid*) lua_touserdata(lua, top); *result = enif_make_pid(env, userdata); lua_pop(lua, 3); assert(lua_gettop(lua) == top-1); return 1; } // pop the pid metatable lua_pop(lua, 1); // push the ref metatable luaL_getmetatable(lua, TYPE_ERL_REF); if(lua_compare(lua, -1, -2, LUA_OPEQ)) { erlref_ptr erlref = (erlref_ptr) lua_touserdata(lua, top); *result = enif_make_copy( env, erlref->reference ); lua_pop(lua, 3); assert(lua_gettop(lua) == top-1); return 1; } lua_pop(lua, 1); // pop the ref metatable luaL_getmetatable(lua, TYPE_LUA_ADDRESS); if(lua_compare(lua, -1, -2, LUA_OPEQ)) { mailbox_address_ptr address = (mailbox_address_ptr) lua_touserdata(lua, top); assert(NULL != address); state_work_ptr state_work = address->state_work; assert(NULL != state_work); void* resource; (*result) = state_make_resource( env, &resource, resource_type, state_work, WEAK_REF); assert(NULL != resource); lua_pop(lua, 3); assert(lua_gettop(lua) == top-1); return 1; } // pop the metatable lua_pop(lua, 1); } lua_pop( lua, 2); *result = enif_make_atom(env, "unknown_lua_userdata"); assert(lua_gettop(lua) == top-1); return 1; break; } case LUA_TLIGHTUSERDATA: { *result = enif_make_atom(env, "lua_lightuserdata_notsupported"); lua_pop(lua, 1); assert(lua_gettop(lua) == top-1); return 1; break; } case LUA_TTHREAD: { *result = enif_make_atom(env, "lua_thread_notsupported"); lua_pop(lua, 1); assert(lua_gettop(lua) == top-1); return 1; break; } case LUA_TFUNCTION: { *result = enif_make_atom(env, "lua_function_notsupported"); lua_pop(lua, 1); assert(lua_gettop(lua) == top-1); return 1; break; } } assert(lua_gettop(lua) == top-1); return 0; }
static ERL_NIF_TERM make_term_caller_pid(struct make_term_info* mti, int n) { ErlNifPid pid; return enif_make_pid(mti->dst_env, enif_self(mti->caller_env, &pid)); }