Current section
Files
Jump to
Current section
Files
src/bardecode.c
#include <string.h>
#include "erl_nif.h"
#include "barcode.h"
// TODO: dirty NIF http://erlang.org/doc/man/erl_nif.html
// get_string gets an Elixir string (binary)
// the caller is responsible for freeing the returned pointer.
static char * get_string(ErlNifEnv *env, ERL_NIF_TERM term) {
ErlNifBinary bin;
if (!enif_inspect_iolist_as_binary(env, term, &bin)) {
return NULL;
}
char *str = strndup((char*) bin.data, bin.size);
enif_release_binary(&bin);
return str;
}
// make_string makes an Elixir string (binary)
static ERL_NIF_TERM make_string(ErlNifEnv *env, const char *str) {
ERL_NIF_TERM result;
size_t size = strlen(str);
unsigned char *chars = enif_make_new_binary(env, size, &result);
strncpy((char *)chars, str, size);
return result;
}
static ERL_NIF_TERM read_barcode(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
char *file = get_string(env, argv[0]);
if (!file) {
return enif_make_badarg(env);
}
char *license = get_string(env, argv[1]);
if (!license) {
return enif_make_badarg(env);
}
// create bar code session with appropriate parameters.
void *hBarcode = STCreateBarCodeSession();
uint16 ival = 1;
STSetParameter(hBarcode, ST_MULTIPLE_READ, &ival);
STSetParameter(hBarcode, ST_READ_PDF417, &ival);
STSetParameter(hBarcode, ST_READ_CODE128, &ival);
STSetParameter(hBarcode, ST_LICENSE, license);
// read bar codes
char **bar_codes_value;
char **bar_codes_type;
int bar_count = STReadBarCode(hBarcode, file, 0, &bar_codes_value, &bar_codes_type);
// return errors as an {:error, "message"} tuple.
if (bar_count < 0) {
ERL_NIF_TERM message;
switch(bar_count) {
case ST_ERROR_FILE_OPEN:
message = make_string(env, "cannot open image file");
break;
default:
message = make_string(env, "error reading image file");
}
free(file);
free(license);
return enif_make_tuple2(env, enif_make_atom(env, "error"), message);
}
// make an empty list to populate
ERL_NIF_TERM barcodes = enif_make_list(env, 0);
// make :kind and :value atoms as keys for the maps
ERL_NIF_TERM atom_kind = enif_make_atom(env, "kind");
ERL_NIF_TERM atom_value = enif_make_atom(env, "rawValue");
// make a map for each barcode and append to the list.
for (int n = 0; n < bar_count; n++) {
ERL_NIF_TERM barcode = enif_make_new_map(env);
enif_make_map_put(env, barcode, atom_kind, make_string(env, bar_codes_type[n]), &barcode);
enif_make_map_put(env, barcode, atom_value, make_string(env, bar_codes_value[n]), &barcode);
barcodes = enif_make_list_cell(env, enif_make_list1(env, barcode), barcodes);
}
// clean up
STFreeBarCodeSession(hBarcode);
free(file);
free(license);
return enif_make_tuple2(env, enif_make_atom(env, "ok"), barcodes);
}
// TODO: add a function that uses ReadBarCodeFromBitmap instead of a file.
// Let's define the array of ErlNifFunc beforehand:
static ErlNifFunc nif_funcs[] = {
// {erl_function_name, erl_function_arity, c_function}
{"read_barcode", 2, read_barcode}
};
ERL_NIF_INIT(Elixir.Bardecode, nif_funcs, NULL, NULL, NULL, NULL)