ERL_NIF_TERM meter_stats(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { meter_handle* handle; if (enif_get_resource(env,argv[0],meter_RESOURCE,(void**)&handle)) { pthread_mutex_lock(&(handle->m)); ERL_NIF_TERM result = enif_make_list4(env, enif_make_tuple2(env,ATOM_COUNT, enif_make_ulong(env, handle->p->count())), enif_make_tuple2(env,ATOM_ONE, enif_make_double(env,handle->p->one())), enif_make_tuple2(env,ATOM_FIVE,enif_make_double(env, handle->p->five())), enif_make_tuple2(env,ATOM_FIFTEEN,enif_make_double(env, handle->p->fifteen()))); pthread_mutex_unlock(&(handle->m)); return result; } else return enif_make_badarg(env); }
ERL_NIF_TERM meter_new(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { meter_handle *handle = (meter_handle *)enif_alloc_resource(meter_RESOURCE, sizeof(meter_handle)); if (enif_is_list(env, argv[0])) { memset(handle, '\0', sizeof(meter_handle)); pthread_mutex_init(&(handle->m), NULL); handle->tick_interval = DEFAULT_METER_TICK_INTERVAL; fold(env, argv[0], parse_meter_option, *handle); handle->p = new meter<>(handle->tick_interval); ERL_NIF_TERM result = enif_make_resource(env, handle); enif_release_resource(handle); return enif_make_tuple2(env, ATOM_OK, result); } else { return enif_make_badarg(env); } }
static ERL_NIF_TERM set_time_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno; Sint64 accessed, modified, created; efile_path_t path; ASSERT(argc == 4); if(!enif_get_int64(env, argv[1], &accessed) || !enif_get_int64(env, argv[2], &modified) || !enif_get_int64(env, argv[3], &created)) { return enif_make_badarg(env); } if((posix_errno = efile_marshal_path(env, argv[0], &path))) { return posix_error_to_tuple(env, posix_errno); } else if((posix_errno = efile_set_time(&path, accessed, modified, created))) { return posix_error_to_tuple(env, posix_errno); } return am_ok; }
static ERL_NIF_TERM emmap_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { mhandle *handle; if (argc==1 && enif_get_resource(env, argv[0], MMAP_RESOURCE, (void**)&handle)) { int res; RW_LOCK; res = emmap_unmap(handle, false); RW_UNLOCK; if (res == 0) { return ATOM_OK; } return make_error_tuple(env, errno); } else { return enif_make_badarg(env); } }
ERL_NIF_TERM _hi_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { hi_ctx_t* ctx = NULL; ErlNifResourceType* ctx_type = get_hi_ctx_type(env); if (ctx_type != NULL && !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx)) { return enif_make_badarg(env); } if (ctx != NULL && ctx->opts != NULL) { enif_free(ctx->opts); enif_free(ctx->iter); ctx->opts = NULL; ctx->iter = NULL; } return ATOM_OK; }
static ERL_NIF_TERM open_tty(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { char ttyname[MAXPATHLEN]; int ttyfd = -1; if (enif_get_string(env, argv[0], ttyname, sizeof(ttyname), ERL_NIF_LATIN1) < 1) { return enif_make_badarg(env); } ttyfd = open(ttyname, O_RDWR|O_NOCTTY|O_NONBLOCK); if (ttyfd < 0) { return mk_errno(env, errno); } return enif_make_tuple2(env, atom_ok, enif_make_int(env, ttyfd)); }
// Create a new scanner resource ERL_NIF_TERM yang_scan_new(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { yang_scanner_t* obj; ERL_NIF_TERM r; if (!(obj = enif_alloc_resource(yang_scan_resource, sizeof(yang_scanner_t)))) return enif_make_badarg(env); obj->line = 1; obj->column = 1; obj->t_line = 0; obj->t_column = 0; obj->t_skip = false; obj->state = STATE_WSP; obj->n_tokens = 0; obj->first = NULL; obj->last = NULL; obj->pos = 0; r = enif_make_resource(env, obj); enif_release_resource(obj); return r; }
static ERL_NIF_TERM make_new_resource_binary(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary data_bin; union { struct binary_resource* p; void* vp; long l;} br; void* buf; ERL_NIF_TERM ret; if (!enif_inspect_binary(env, argv[0], &data_bin) || (br.vp = enif_alloc_resource(binary_resource_type, sizeof(struct binary_resource)))==NULL || (buf = enif_alloc(data_bin.size)) == NULL) { return enif_make_badarg(env); } memset(br.vp,0xba,sizeof(struct binary_resource)); /* avoid valgrind warning */ br.p->data = buf; br.p->size = data_bin.size; memcpy(br.p->data, data_bin.data, data_bin.size); ret = enif_make_resource_binary(env, br.vp, br.p->data, br.p->size); enif_release_resource(br.p); return enif_make_tuple2(env, enif_make_long(env,br.l), ret); }
ERL_NIF_TERM pteracuda_nifs_new_context(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { CUdevice device; int deviceNum = 0; PCudaContextRef *ref = (PCudaContextRef *) enif_alloc_resource(pteracuda_context_resource, sizeof(PCudaContextRef)); if (!ref) { return OOM_ERROR; } if (argc == 1 && !enif_get_int(env, argv[0], &deviceNum)) { return enif_make_badarg(env); } if (cuDeviceGet(&device, deviceNum) == CUDA_SUCCESS && cuCtxCreate(&(ref->ctx), CU_CTX_SCHED_AUTO, device) == CUDA_SUCCESS) { ref->destroyed = false; ERL_NIF_TERM result = enif_make_resource(env, ref); enif_release_resource(ref); return enif_make_tuple2(env, ATOM_OK, result); } else { return ATOM_ERROR; } }
static ERL_NIF_TERM decode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary input; ERL_NIF_TERM result; unsigned int flags; yaml_parser_t parser; if (argc == 2) { if (enif_inspect_iolist_as_binary(env, argv[0], &input) && enif_get_uint(env, argv[1], &flags)) { yaml_parser_initialize(&parser); result = parse(env, &parser, flags, input.data, input.size); yaml_parser_delete(&parser); return result; } } return enif_make_badarg(env); }
ERL_NIF_TERM pteracuda_nifs_log(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { PCudaContextRef *ctxRef; PCudaBufferRef *ref_A, *ref_B; if (argc != 3 || !enif_get_resource(env, argv[0], pteracuda_context_resource, (void **) &ctxRef) || !enif_get_resource(env, argv[1], pteracuda_buffer_resource, (void **) &ref_A) || !enif_get_resource(env, argv[2], pteracuda_buffer_resource, (void **) &ref_B) ) { return enif_make_badarg(env); } if(((PCudaFloatBuffer*)ref_A->buffer)->size() != ((PCudaFloatBuffer*)ref_B->buffer)->size()){ return enif_make_tuple2(env, ATOM_ERROR, enif_make_atom(env, "Buffer A size does not match buffer B size")); } cuCtxSetCurrent(ctxRef->ctx); pcuda_log(((PCudaFloatBuffer*)ref_A->buffer)->get_data(), ((PCudaFloatBuffer*)ref_B->buffer)->get_data()); return ATOM_OK; }
static ERL_NIF_TERM nacl_box_open_padded(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary padded_ciphertext; ErlNifBinary nonce; ErlNifBinary pk; ErlNifBinary sk; ErlNifBinary result; if (!enif_inspect_iolist_as_binary(env, argv[0], &padded_ciphertext)) return enif_make_badarg(env); if (!enif_inspect_iolist_as_binary(env, argv[1], &nonce)) return enif_make_badarg(env); if (!enif_inspect_iolist_as_binary(env, argv[2], &pk)) return enif_make_badarg(env); if (!enif_inspect_iolist_as_binary(env, argv[3], &sk)) return enif_make_badarg(env); if (nonce.size != crypto_box_NONCEBYTES) return enif_make_badarg(env); if (pk.size != crypto_box_PUBLICKEYBYTES) return enif_make_badarg(env); if (sk.size != crypto_box_SECRETKEYBYTES) return enif_make_badarg(env); if (padded_ciphertext.size < crypto_box_BOXZEROBYTES) return enif_make_badarg(env); if (!enif_alloc_binary(padded_ciphertext.size, &result)) return nacl_error_tuple(env, "alloc_failed"); if (crypto_box_open(result.data, padded_ciphertext.data, padded_ciphertext.size, nonce.data, pk.data, sk.data)) { return nacl_error_tuple(env, "crypto_failed"); } return enif_make_sub_binary(env, enif_make_binary(env, &result), crypto_box_ZEROBYTES, padded_ciphertext.size - crypto_box_ZEROBYTES); }
static ERL_NIF_TERM file_handle_wrapper(file_op_impl_t operation, ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { efile_data_t *d; enum efile_state_t previous_state; ERL_NIF_TERM result; if(argc < 1 || !get_file_data(env, argv[0], &d)) { return enif_make_badarg(env); } previous_state = erts_atomic32_cmpxchg_acqb(&d->state, EFILE_STATE_BUSY, EFILE_STATE_IDLE); if(previous_state == EFILE_STATE_IDLE) { result = operation(d, env, argc - 1, &argv[1]); previous_state = erts_atomic32_cmpxchg_relb(&d->state, EFILE_STATE_IDLE, EFILE_STATE_BUSY); ASSERT(previous_state != EFILE_STATE_IDLE); if(previous_state == EFILE_STATE_CLOSE_PENDING) { /* This is the only point where a change from CLOSE_PENDING is * possible, and we're running synchronously, so we can't race with * anything else here. */ erts_atomic32_set_acqb(&d->state, EFILE_STATE_CLOSED); efile_close(d); } } else { /* CLOSE_PENDING should be impossible at this point since it requires * a transition from BUSY; the only valid state here is CLOSED. */ ASSERT(previous_state == EFILE_STATE_CLOSED); result = posix_error_to_tuple(env, EINVAL); } return result; }
ERL_NIF_TERM engine_free_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Engine) */ #ifdef HAS_ENGINE_SUPPORT struct engine_ctx *ctx; // Get Engine ASSERT(argc == 1); if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) goto bad_arg; if (!ENGINE_free(ctx->engine)) goto err; return atom_ok; bad_arg: err: return enif_make_badarg(env); #else return atom_notsup; #endif }
ERL_NIF_TERM histogram_new(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { histogram_handle *handle = (histogram_handle *)enif_alloc_resource(histogram_RESOURCE, sizeof(histogram_handle)); if (enif_is_list(env, argv[0])) { memset(handle, '\0', sizeof(histogram_handle)); pthread_mutex_init(&(handle->m), NULL); handle->size = DEFAULT_RESERVOIR_SIZE; handle->width = DEFAULT_WINDOW_WIDTH; fold(env, argv[0], parse_histogram_option, *handle); handle->p = new histogram<>(handle->size, handle->width); ERL_NIF_TERM result = enif_make_resource(env, handle); enif_release_resource(handle); return enif_make_tuple2(env, ATOM_OK, result); } else { return enif_make_badarg(env); } }
static ERL_NIF_TERM pread_nif_impl(efile_data_t *d, ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { Sint64 bytes_read, block_size, offset; SysIOVec read_vec[1]; ErlNifBinary result; ASSERT(argc == 2); if(!enif_is_number(env, argv[0]) || !enif_is_number(env, argv[1])) { return enif_make_badarg(env); } if(!enif_get_int64(env, argv[0], &offset) || !enif_get_int64(env, argv[1], &block_size) || (offset < 0 || block_size < 0)) { return posix_error_to_tuple(env, EINVAL); } if(!enif_alloc_binary(block_size, &result)) { return posix_error_to_tuple(env, ENOMEM); } read_vec[0].iov_base = result.data; read_vec[0].iov_len = result.size; bytes_read = efile_preadv(d, offset, read_vec, 1); if(bytes_read < 0) { enif_release_binary(&result); return posix_error_to_tuple(env, d->posix_errno); } else if(bytes_read == 0) { enif_release_binary(&result); return am_eof; } if(bytes_read < block_size && !enif_realloc_binary(&result, bytes_read)) { ERTS_INTERNAL_ERROR("Failed to shrink pread result."); } return enif_make_tuple2(env, am_ok, enif_make_binary(env, &result)); }
ERL_NIF_TERM date_roll(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { UErrorCode status = U_ZERO_ERROR; UCalendar* cal; cloner* ptr; double date; if(!((argc == 3) && enif_get_resource(env, argv[0], calendar_type, (void**) &ptr) && enif_get_double(env, argv[1], &date))) { return enif_make_badarg(env); } cal = (UCalendar*) cloner_get(ptr); CHECK_RES(env, cal); ucal_setMillis(cal, (UDate) date, &status); CHECK(env, status); return do_offset(env, cal, ucal_roll, argv[2]); }
/** * Erlang Wrapper for geonum_decode_bbox */ ERL_NIF_TERM erl_geonum_decode_bbox(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { double tl[2], br[2]; long long geonum; if(!enif_get_int64(env, argv[0], &geonum)) { return enif_make_badarg(env); } geonum_decode_bbox(geonum, tl, br); ERL_NIF_TERM top_left = enif_make_tuple2(env, enif_make_double(env, tl[0]), enif_make_double(env, tl[1])); ERL_NIF_TERM bottom_right = enif_make_tuple2(env, enif_make_double(env, br[0]), enif_make_double(env, br[1])); ERL_NIF_TERM bbox = enif_make_tuple2(env, top_left, bottom_right); return make_ok(env, bbox); }
static ERL_NIF_TERM mem_alloc(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ptr_t ptr, size, err; err = nifty_get_ptr(env, argv[0], &size); if (!err) { goto error; } ptr = (ptr_t)enif_alloc(size); if (!ptr) { goto error; } return enif_make_tuple2(env, nifty_make_ptr(env, (ptr_t)ptr), enif_make_string(env, "nifty.void *", ERL_NIF_LATIN1)); error: return enif_make_badarg(env); }
static ERL_NIF_TERM get_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary data_bin; union { ErlNifResourceType* t; long l; } type; union { void* p; long l; } data; type.t = NULL; if (enif_is_identical(argv[0], atom_binary_resource_type)) { type.t = binary_resource_type; } else { enif_get_long(env, argv[0], &type.l); } if (type.t == NULL || !enif_get_resource(env, argv[1], type.t, &data.p)) { return enif_make_badarg(env); } enif_alloc_binary(enif_sizeof_resource(data.p), &data_bin); memcpy(data_bin.data, data.p, data_bin.size); return enif_make_tuple2(env, enif_make_long(env,data.l), enif_make_binary(env, &data_bin)); }
ERL_NIF_TERM pteracuda_ml_gd(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { PCudaContextRef *ctxRef; PCudaBufferRef *ref_Theta, *ref_X, *ref_Y; unsigned long num_features, num_samples; if (argc != 6 || !enif_get_resource(env, argv[0], pteracuda_context_resource, (void **) &ctxRef) || !enif_get_resource(env, argv[1], pteracuda_buffer_resource, (void **) &ref_Theta) || !enif_get_resource(env, argv[2], pteracuda_buffer_resource, (void **) &ref_X) || !enif_get_resource(env, argv[3], pteracuda_buffer_resource, (void **) &ref_Y) || !enif_get_ulong(env, argv[4], &num_features) || !enif_get_ulong(env, argv[5], &num_samples) ) { return enif_make_badarg(env); } cuCtxSetCurrent(ctxRef->ctx); pcuda_gd(((PCudaFloatBuffer*)ref_Theta->buffer)->get_data(), ((PCudaFloatBuffer*)ref_X->buffer)->get_data(), ((PCudaFloatBuffer*)ref_Y->buffer)->get_data(), num_features, num_samples); return ATOM_OK; }
ERL_NIF_TERM _hh_count_at(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { int64_t value = 0; hh_ctx_t* ctx = NULL; ErlNifResourceType* ctx_type = get_hh_ctx_type(env); if (argc != 2 || ctx_type == NULL || !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx) || ctx->data == NULL || !enif_get_int64(env, argv[1], &value)) { return enif_make_badarg(env); } if (ctx != NULL) { return enif_make_int64(env, hdr_count_at_value(ctx->data, value)); } return make_error(env, "bad_hdr_histogram_nif_impl"); }
static ERL_NIF_TERM transpose(ErlNifEnv *env, int32_t argc, const ERL_NIF_TERM *argv) { ErlNifBinary matrix; ERL_NIF_TERM result; float *matrix_data, *result_data; int32_t data_size; size_t result_size; (void)(argc); if (!enif_inspect_binary(env, argv[0], &matrix)) return enif_make_badarg(env); matrix_data = (float *) matrix.data; data_size = (int32_t) (matrix_data[0] * matrix_data[1] + 2); result_size = sizeof(float) * data_size; result_data = (float *) enif_make_new_binary(env, result_size, &result); matrix_transpose(matrix_data, result_data); return result; }
static ERL_NIF_TERM to_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { /* to_term(Matrix) -> [[first row], [second row], ...,[last row]] */ unsigned i, j; ERL_NIF_TERM res; mx_t mx; mx.p = NULL; if (!enif_get_resource(env, argv[0], resource_type, &mx.vp)) { return enif_make_badarg(env); } res = enif_make_list(env, 0); for (i = mx.p->nrows; i-- > 0; ) { ERL_NIF_TERM row = enif_make_list(env, 0); for (j = mx.p->ncols; j-- > 0; ) { row = enif_make_list_cell(env, enif_make_double(env, POS(mx.p,i,j)), row); } res = enif_make_list_cell(env, row, res); } return res; }
static ERL_NIF_TERM _close (ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { CAN_handle* handle; ERL_NIF_TERM result; if (!enif_get_resource(env, argv[0], CAN_handle_type, (void**) &handle)) return enif_make_badarg(env);; if (handle->threaded) { void* dont_care; handle->threaded = 0; enif_thread_join(handle->tid, &dont_care); } result = enif_make_int(env, handle->device >= 0 ? close(handle->device) : 0); handle->device = -1; if (handle->devpath) { enif_free(handle->devpath); handle->devpath = NULL; } return result; }
static ERL_NIF_TERM write_nif_impl(efile_data_t *d, ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ErlNifIOVec vec, *input = &vec; Sint64 bytes_written; ERL_NIF_TERM tail; if(argc != 1 || !enif_inspect_iovec(env, 64, argv[0], &tail, &input)) { return enif_make_badarg(env); } bytes_written = efile_writev(d, input->iov, input->iovcnt); if(bytes_written < 0) { return posix_error_to_tuple(env, d->posix_errno); } if(!enif_is_empty_list(env, tail)) { ASSERT(bytes_written > 0); return enif_make_tuple2(env, am_continue, tail); } return am_ok; }
static ERL_NIF_TERM rotate(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { double angle; int arity; const ERL_NIF_TERM *t,*v; double dm[16]; ERL_NIF_TERM d[16]; if(!enif_get_tuple(env,argv[0],&arity,&t)) { return enif_make_badarg(env); } if(arity!=16) { return enif_make_badarg(env); } for(int i=0; i<16; ++i) { enif_get_double(env,t[i],&dm[i]); } glm::dmat4 matrix = glm::make_mat4(dm); if(!enif_get_double(env,argv[1],&angle)) { return enif_make_badarg(env); } if(!enif_get_tuple(env,argv[2],&arity,&v)) { return enif_make_badarg(env); } if(arity != 3) { return enif_make_badarg(env); } glm::dvec3 axis; if(!(enif_get_double(env,v[0],&axis.x) && enif_get_double(env,v[1],&axis.y) && enif_get_double(env,v[2],&axis.z))) { return enif_make_badarg(env); } glm::dmat4 rotation = glm::rotate(matrix,angle,axis); const double *pSource = (const double*)glm::value_ptr(rotation); for(int i =0; i<16; ++i) { d[i] = enif_make_double(env,pSource[i]); } return enif_make_tuple_from_array(env,d,16); }
static ERL_NIF_TERM advise_nif_impl(efile_data_t *d, ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { enum efile_advise_t advise; Sint64 offset, length; if(argc != 3 || !enif_is_number(env, argv[0]) || !enif_is_number(env, argv[1])) { return enif_make_badarg(env); } if(!enif_get_int64(env, argv[0], &offset) || !enif_get_int64(env, argv[1], &length) || (offset < 0 || length < 0)) { return posix_error_to_tuple(env, EINVAL); } if(enif_is_identical(argv[2], am_normal)) { advise = EFILE_ADVISE_NORMAL; } else if(enif_is_identical(argv[2], am_random)) { advise = EFILE_ADVISE_RANDOM; } else if(enif_is_identical(argv[2], am_sequential)) { advise = EFILE_ADVISE_SEQUENTIAL; } else if(enif_is_identical(argv[2], am_will_need)) { advise = EFILE_ADVISE_WILL_NEED; } else if(enif_is_identical(argv[2], am_dont_need)) { advise = EFILE_ADVISE_DONT_NEED; } else if(enif_is_identical(argv[2], am_no_reuse)) { advise = EFILE_ADVISE_NO_REUSE; } else { /* The tests check for EINVAL instead of badarg. Sigh. */ return posix_error_to_tuple(env, EINVAL); } if(!efile_advise(d, offset, length, advise)) { return posix_error_to_tuple(env, d->posix_errno); } return am_ok; }
ERL_NIF_TERM engine_get_first_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* () */ #ifdef HAS_ENGINE_SUPPORT ERL_NIF_TERM ret, result; ENGINE *engine; ErlNifBinary engine_bin; struct engine_ctx *ctx = NULL; ASSERT(argc == 0); if ((engine = ENGINE_get_first()) == NULL) { if (!enif_alloc_binary(0, &engine_bin)) goto err; engine_bin.size = 0; return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_bin)); } if ((ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx))) == NULL) goto err; ctx->engine = engine; ctx->id = NULL; result = enif_make_resource(env, ctx); ret = enif_make_tuple2(env, atom_ok, result); goto done; err: ret = enif_make_badarg(env); done: if (ctx) enif_release_resource(ctx); return ret; #else return atom_notsup; #endif }
ERL_NIF_TERM _hh_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { long highest_trackable_value = 0; int significant_figures = 0; if (argc != 2 || !enif_get_int64(env, argv[0], &highest_trackable_value) || !enif_get_int(env, argv[1], &significant_figures)) { return enif_make_badarg(env); } hdr_histogram_t* raw_histogram; int rc = 0; rc = hdr_alloc(highest_trackable_value, significant_figures, &raw_histogram); if (EINVAL == rc) { return make_error(env, "bad_significant_factor"); } if (ENOMEM == rc) { return make_error(env, "not_enough_memory"); } ErlNifResourceType* ctx_type = get_hh_ctx_type(env); hh_ctx_t* ctx = (hh_ctx_t*)enif_alloc_resource(ctx_type, sizeof(hh_ctx_t)); ctx->data = raw_histogram; ctx->highest_trackable_value = highest_trackable_value; ctx->significant_figures = significant_figures; ERL_NIF_TERM result = enif_make_resource(env, ctx); enif_release_resource(ctx); return enif_make_tuple2(env, ATOM_OK, result); }