Source

hello / erlang / test_nif.c

/* test_nif.c: filename and function names should be same name with the erlang module
 $ gcc -fPIC -shared -o niftest.so niftest.c -I $ERL_ROOT/usr/include/
 */
#include "erl_nif.h"
#include <stdio.h>
#include <string.h>

typedef struct mydata_ {
  void * ptr;
  size_t size;
} my;

static ERL_NIF_TERM hello(ErlNifEnv* env)
{
  return enif_make_string(env, "Hello world!");
}

static ERL_NIF_TERM set(ErlNifEnv* env, ERL_NIF_TERM value){
  my * bin = enif_get_data(env);
  ErlNifBinary tmp;
  if( bin->ptr != NULL ){
    enif_free( env, bin->ptr );
  }
  if( enif_inspect_binary(env, value, &tmp) ){
    bin->size = tmp.size;
    bin->ptr = enif_alloc(env,  bin->size );
    memcpy( bin->ptr, tmp.data, bin->size );
    //    fprintf(stderr, "%s %d: %s\n", __FILE__, __LINE__, );
    return enif_make_string(env, "ok");
  }else{
    fprintf(stderr, "%s %d: %p\n", __FILE__, __LINE__, bin->ptr);
    return enif_make_string(env, "fail");
  }
}

static ERL_NIF_TERM get(ErlNifEnv* env){
  my * bin = enif_get_data(env);
  ErlNifBinary tmp;
  fprintf(stderr, "%s %d: %d\n", __FILE__, __LINE__, (int)bin->size);
  if( bin->ptr != NULL ){
    int i;
    for( i = 0; i < bin->size ; ++i){
      printf( "%x ", *(char*)(bin->ptr + i) );
    }
    printf("\n");
    enif_alloc_binary(env, bin->size, &tmp);
    memcpy( tmp.data, bin->ptr, bin->size );
    ERL_NIF_TERM ret = enif_make_binary(env, &tmp);
    fprintf(stderr, "%s %d: %p\n", __FILE__, __LINE__, &tmp);
    return ret;
  }else{
    return enif_make_string(env, "none");
  }
}

static inspector(ERL_NIF_TERM term){
  //  if(is_atom(term)) printf("atom.\n");
}

static ERL_NIF_TERM p2(ErlNifEnv* env, ERL_NIF_TERM lhs, ERL_NIF_TERM rhs){
  inspector(lhs);
  inspector(rhs);
  return enif_make_string(env, "hoge");
}

static ErlNifFunc nif_funcs[] =
{
  {"hello", 0, hello},
  {"set", 1, set},
  {"get", 0, get},
  {"p",   2, p2}
};

int load_(ErlNifEnv *env, void ** priv_data, ERL_NIF_TERM load_info){
  fprintf(stderr, "%s %d:\n", __FILE__, __LINE__ );
  my * d = enif_alloc(env, sizeof(my) );
  d->ptr = NULL;
  d->ptr = 0;
  *priv_data = (void*)d;
  //memset( *priv_data , 0x00, sizeof(ErlNifBinary) );
  return 0; 
  //return 1; fails anything other than 0.
}
int reload_(ErlNifEnv *env, void ** priv_data, ERL_NIF_TERM load_info){
  return 0; 
  //return 1; fails anything other than 0.
}
int upgrade_(ErlNifEnv *env, void ** priv_data, void ** old_priv_data, ERL_NIF_TERM load_info){
  *priv_data = *old_priv_data;
  return 0; 
  //return 1; fails anything other than 0.
}
void unload_(ErlNifEnv *env, void* priv_data){
  my * bin = (my*)priv_data;
  fprintf(stderr, "%s %d: \n", __FILE__, __LINE__ );
  return; 
}


//ERL_NIF_INIT(test_nif,nif_funcs,NULL,NULL,NULL,NULL)
ERL_NIF_INIT(test_nif,nif_funcs,load_,reload_,upgrade_,unload_);