0

我正在使用 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多少?double insideERL_NIF_TERM与 int inside 的大小相同ERL_NIF_TERM吗?一个 2 个整数的元组也是一个ERL_NIF_TERM,它的大小是否相同?

4

1 回答 1

3

不,您的双精度值和 2,3 元组是在堆上分配的。它由env变量访问。所以你必须只为ntri ERL_NIF_TERM你存储的 s 分配空间。它们是您enif_make_tuple3调用的结果。您还应该使用enif_allocfor allocation 而不是malloc尽可能(在您自己的代码中)。Sou 您的代码应如下所示:

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 上的 4B 或 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;
于 2016-02-18T11:12:44.507 回答