#include "erl_nif.h" #define A_OK(env) enif_make_atom(env, "ok") #define assert_badarg(S, Env) if (! S) { return enif_make_badarg(env); } static ErlNifResourceType* array_handle = NULL; static void array_handle_cleanup(ErlNifEnv* env, void* arg) {} static int load(ErlNifEnv* env, void** priv, ERL_NIF_TERM load_info) { ErlNifResourceFlags flags = ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER; array_handle = enif_open_resource_type(env, "native_array_nif", "array_handle", &array_handle_cleanup, flags, 0); // 用于存储指针的数组, 最多1000个array *priv = enif_alloc(1000 * sizeof(void*)); return 0; } static void unload(ErlNifEnv* env, void* priv) { enif_free(priv); } static ERL_NIF_TERM new_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { // 取参数 int refindex; assert_badarg(enif_get_int(env, argv[0], &refindex), env); // 取参数length unsigned long length; assert_badarg(enif_get_ulong(env, argv[1], &length), env); // 分配内存 // unsigned char* ref = enif_alloc_resource(array_handle, length); unsigned char* ref = enif_alloc(length); // 保存指针 *((unsigned char**)enif_priv_data(env) + refindex) = ref; return A_OK(env); } static ERL_NIF_TERM get_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { // 取参数ref int refindex; assert_badarg(enif_get_int(env, argv[0], &refindex), env); unsigned char* ref = *((unsigned char**)enif_priv_data(env) + refindex); assert_badarg(ref, env); // 取参数offset unsigned long offset; assert_badarg(enif_get_ulong(env, argv[1], &offset), env); return enif_make_int(env, (int)(*(ref + offset - 1))); } static ERL_NIF_TERM put_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { // 取参数ref int refindex; assert_badarg(enif_get_int(env, argv[0], &refindex), env); unsigned char* ref = *((unsigned char**)enif_priv_data(env) + refindex); // 取参数offset unsigned long offset; assert_badarg(enif_get_ulong(env, argv[1], &offset), env); // 取参数newval unsigned int newval; assert_badarg(enif_get_uint(env, argv[2], &newval), env); // 赋值 *(ref + offset - 1) = (unsigned char)newval; return A_OK(env); } static ERL_NIF_TERM delete_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { // 取参数ref int refindex; assert_badarg(enif_get_int(env, argv[0], &refindex), env); unsigned char* ref = *((unsigned char**)enif_priv_data(env) + refindex); //enif_release_resource(ref); enif_free(ref); return A_OK(env); } static ErlNifFunc nif_funcs[] = { {"new", 2, new_nif}, {"get", 2, get_nif}, {"put", 3, put_nif}, {"delete", 1, delete_nif}, }; ERL_NIF_INIT(native_array, nif_funcs, &load, NULL, NULL, &unload)