#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)
|
|
|