0

私は Erlang の NIF を使用しています。C 関数の結果は、3 つのポイントのタプルのリストの形式で erlang に送り返したい配列であり、それぞれが 2 つの double のタプルです。

この配列を作成するには、現在これを行っています:

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、サイズが の double が 6 つあるERL_NIF_TERMため、これに従って割り当てます。

しかし、それは本当ですか?

タプルを数えるべきですか?

一体、どのくらいのサイズERL_NIF_TERMですか?double insideERL_NIF_TERMは int inside と同じサイズERL_NIF_TERMでしょうか? 2 int のタプルもERL_NIF_TERM同じサイズですか?

4

1 に答える 1

3

いいえ、double 値と 2,3-tuples はヒープに割り当てられます。変数によってアクセスされenvます。したがって、ntri ERL_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;

2番目の質問ですが、とにかくサイズは何ですか? 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;
于 2016-02-18T11:12:44.507 に答える