2016-02-18 2 views
0

Я использую NIF Erlang, а результат функции C - это массив, который я хочу отправить обратно erlang в виде списка кортежей из трех точек, каждый из которых является кортежем из двух парных.Использование NIF Erlang, как использовать malloc в ERL_NIF_TERM?

создать этот массив в настоящее время я делаю это:

ans = (ERL_NIF_TERM *)malloc(6*ntri*sizeof(ERL_NIF_TERM)); 

for (i=0;i<ntri;i++) { 
    ans[i] = enif_make_tuple3(env, 
      enif_make_tuple2(env,enif_make_double(env,x1[i]),enif_make_double(env,y1[i])), 
      enif_make_tuple2(env,enif_make_double(env,x2[i]),enif_make_double(env,y2[i])), 
      enif_make_tuple2(env,enif_make_double(env,x3[i]),enif_make_double(env,y3[i])) 
    ); 
} 

До сих пор, кажется, работает. но это правильно? Мое рассуждение состояло в том, что на каждой ячейке массива ans У меня есть 6 двухместных номеров размером ERL_NIF_TERM, поэтому я выделяю в соответствии с этим.

Но это правда?

Должен ли я считать кортежи?

Какой размер ERL_NIF_TERM в любом случае? Будет ли внутри внутри ERL_NIF_TERM быть такого же размера int внутри ERL_NIF_TERM? кортеж 2 ints также является ERL_NIF_TERM, он такой же размер?

ответ

3

Нет, ваши двойные значения и 2,3-кортежи выделены в куче. К нему обращается переменная env. Поэтому вам нужно выделить только пространство для ntriERL_NIF_TERM s, которое вы храните. Они являются результатом вашего звонка enif_make_tuple3. Вы также должны использовать enif_alloc для распределения вместо malloc всякий раз, когда можете (в своем собственном коде). СОУ ваш код должен выглядеть следующим образом:

ERL_NIF_TERM *ans = enif_alloc(ntri*sizeof(ERL_NIF_TERM)); 
if(!ans) return enif_raise_exception(env, enif_make_atom(env, "insufficient_memory")); 
// use enif_make_badarg(env) prior to R18 

for (i=0;i<ntri;i++) { 
    ans[i] = enif_make_tuple3(env, 
      enif_make_tuple2(env,enif_make_double(env,x1[i]),enif_make_double(env,y1[i])), 
      enif_make_tuple2(env,enif_make_double(env,x2[i]),enif_make_double(env,y2[i])), 
      enif_make_tuple2(env,enif_make_double(env,x3[i]),enif_make_double(env,y3[i])) 
    ); 
} 

ERL_NIF_TERM result = enif_make_list_from_array(env, ans, ntri); 
enif_free(ans); 
return result; 

Теперь о втором вопросе, Каков размер ERL_NIF_TERM так или иначе? Размер ERL_NIF_TERM - это слово на вашей платформе. Это 8B на 64b и 4B на 32b или 64b полуслова. Он может храниться в стеке или регистрироваться, поэтому вам не нужно выделять требуемую память, и вы можете передать ее как простой параметр для функций.

Редактировать: Вам не нужно выделять память вообще. Более эффективно создавать список результатов напрямую.

ERL_NIF_TERM result = enif_make_list(env, 0); 

for (i = ntri; i;) { 
    i--; 
    result = enif_make_list_cell(env, 
     enif_make_tuple3(env, 
      enif_make_tuple2(env,enif_make_double(env,x1[i]),enif_make_double(env,y1[i])), 
      enif_make_tuple2(env,enif_make_double(env,x2[i]),enif_make_double(env,y2[i])), 
      enif_make_tuple2(env,enif_make_double(env,x3[i]),enif_make_double(env,y3[i])) 
     ), 
     result 
    ); 
} 

return result; 
+0

Хорошо, я думаю, что это больше похоже на какой-то указатель на реальное местоположение на куче, вот и все имеет смысл теперь. – Deddy

+0

@ Deddy: На самом деле это [tagged pointer] (https://stackoverflow.com/a/31839473/49197) –

Смежные вопросы