diff options
Diffstat (limited to 'erts/example/matrix_nif.c')
-rw-r--r-- | erts/example/matrix_nif.c | 87 |
1 files changed, 51 insertions, 36 deletions
diff --git a/erts/example/matrix_nif.c b/erts/example/matrix_nif.c index c5e01dade5..404329e36c 100644 --- a/erts/example/matrix_nif.c +++ b/erts/example/matrix_nif.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2010. All Rights Reserved. + * Copyright Ericsson AB 2010-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -31,7 +31,19 @@ typedef struct unsigned nrows; unsigned ncols; double* data; -}Matrix; +} Matrix; + +/* + * Use a union for pointer type conversion to avoid compiler warnings + * about strict-aliasing violations with gcc-4.1. gcc >= 4.2 does not + * emit the warning. + * TODO: Reconsider use of union once gcc-4.1 is obsolete? + */ +typedef union +{ + void* vp; + Matrix* p; +} mx_t; #define POS(MX, ROW, COL) ((MX)->data[(ROW)* (MX)->ncols + (COL)]) @@ -44,8 +56,9 @@ static ErlNifResourceType* resource_type = NULL; static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { - ErlNifResourceType* rt = enif_open_resource_type(env, "matrix_nif_example", - matrix_dtor, + ErlNifResourceType* rt = enif_open_resource_type(env, NULL, + "matrix_nif_example", + matrix_dtor, ERL_NIF_RT_CREATE, NULL); if (rt == NULL) { return -1; @@ -90,12 +103,12 @@ static ERL_NIF_TERM create(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) } ret = enif_make_resource(env, mx); - enif_release_resource(env, mx); + enif_release_resource(mx); return ret; badarg: if (mx != NULL) { - enif_release_resource(env,mx); + enif_release_resource(mx); } return enif_make_badarg(env); } @@ -104,14 +117,14 @@ badarg: static ERL_NIF_TERM pos(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { /* pos(Matrix, Row, Column) -> float() */ - Matrix* mx; + mx_t mx; unsigned i, j; - if (!enif_get_resource(env, argv[0], resource_type, (void**)&mx) || - !enif_get_uint(env, argv[1], &i) || (--i >= mx->nrows) || - !enif_get_uint(env, argv[2], &j) || (--j >= mx->ncols)) { + if (!enif_get_resource(env, argv[0], resource_type, &mx.vp) || + !enif_get_uint(env, argv[1], &i) || (--i >= mx.p->nrows) || + !enif_get_uint(env, argv[2], &j) || (--j >= mx.p->ncols)) { return enif_make_badarg(env); } - return enif_make_double(env, POS(mx, i,j)); + return enif_make_double(env, POS(mx.p, i,j)); } static ERL_NIF_TERM add(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) @@ -119,37 +132,38 @@ static ERL_NIF_TERM add(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) /* add(Matrix_A, Matrix_B) -> Matrix_Sum */ unsigned i, j; ERL_NIF_TERM ret; - Matrix* mxA = NULL; - Matrix* mxB = NULL; - Matrix* mxS = NULL; + mx_t mxA, mxB, mxS; + mxA.p = NULL; + mxB.p = NULL; + mxS.p = NULL; - if (!enif_get_resource(env, argv[0], resource_type, (void**)&mxA) || - !enif_get_resource(env, argv[1], resource_type, (void**)&mxB) || - mxA->nrows != mxB->nrows || - mxB->ncols != mxB->ncols) { + if (!enif_get_resource(env, argv[0], resource_type, &mxA.vp) || + !enif_get_resource(env, argv[1], resource_type, &mxB.vp) || + mxA.p->nrows != mxB.p->nrows || + mxB.p->ncols != mxB.p->ncols) { return enif_make_badarg(env); } - mxS = alloc_matrix(env, mxA->nrows, mxA->ncols); - for (i = 0; i < mxA->nrows; i++) { - for (j = 0; j < mxA->ncols; j++) { - POS(mxS, i, j) = POS(mxA, i, j) + POS(mxB, i, j); + mxS.p = alloc_matrix(env, mxA.p->nrows, mxA.p->ncols); + for (i = 0; i < mxA.p->nrows; i++) { + for (j = 0; j < mxA.p->ncols; j++) { + POS(mxS.p, i, j) = POS(mxA.p, i, j) + POS(mxB.p, i, j); } } - ret = enif_make_resource(env, mxS); - enif_release_resource(env, mxS); + ret = enif_make_resource(env, mxS.p); + enif_release_resource(mxS.p); return ret; } static ERL_NIF_TERM size_of(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { /* size(Matrix) -> {Nrows, Ncols} */ - Matrix* mx; - if (!enif_get_resource(env, argv[0], resource_type, (void**)&mx)) { + mx_t mx; + if (!enif_get_resource(env, argv[0], resource_type, &mx.vp)) { return enif_make_badarg(env); } - return enif_make_tuple2(env, enif_make_uint(env, mx->nrows), - enif_make_uint(env, mx->ncols)); + return enif_make_tuple2(env, enif_make_uint(env, mx.p->nrows), + enif_make_uint(env, mx.p->ncols)); } static ERL_NIF_TERM to_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) @@ -157,16 +171,17 @@ 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; - Matrix* mx = NULL; + mx_t mx; + mx.p = NULL; - if (!enif_get_resource(env, argv[0], resource_type, (void**)&mx)) { + 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->nrows; i-- > 0; ) { + for (i = mx.p->nrows; i-- > 0; ) { ERL_NIF_TERM row = enif_make_list(env, 0); - for (j = mx->ncols; j-- > 0; ) { - row = enif_make_list_cell(env, enif_make_double(env, POS(mx,i,j)), + 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); @@ -183,17 +198,17 @@ static int get_number(ErlNifEnv* env, ERL_NIF_TERM term, double* dp) static Matrix* alloc_matrix(ErlNifEnv* env, unsigned nrows, unsigned ncols) { - Matrix* mx = enif_alloc_resource(env, resource_type, sizeof(Matrix)); + Matrix* mx = enif_alloc_resource(resource_type, sizeof(Matrix)); mx->nrows = nrows; mx->ncols = ncols; - mx->data = enif_alloc(env, nrows*ncols*sizeof(double)); + mx->data = enif_alloc(nrows*ncols*sizeof(double)); return mx; } static void matrix_dtor(ErlNifEnv* env, void* obj) { Matrix* mx = (Matrix*) obj; - enif_free(env, mx->data); + enif_free(mx->data); mx->data = NULL; } |