我正在使用Erlang的NIF,而C函数的结果是一个数组,我希望以三个元组的元组列表的形式发送回erlang,每个元素都是一个元组两个双打。
创建此数组目前我正在执行此操作:
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
内的双重内容与ERL_NIF_TERM
内的int的大小相同吗? 2个整数的元组也是ERL_NIF_TERM
,是否大小相同?
答案 0 :(得分:3)
不,你的双值和2,3元组是在堆上分配的。它由env
变量访问。因此,您只需为您存储的ntri
ERL_NIF_TERM
分配空间。它们是您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
的大小就是您平台上的一个词。它在64b上为8B,在32b或64b上为4B半字。它可以存储在堆栈或寄存器中,因此您不必分配所需的内存,您可以将其作为一个简单的参数传递给函数。
编辑:您根本不需要分配内存。直接构造结果列表更有效。
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;