将复杂的非基元C++数据类型转换为Erlang/Elixir格式,以便使用NIF导出方法

dkqlctbz  于 2022-12-08  发布在  Erlang
关注(0)|答案(1)|浏览(156)

我正在用C编写一个库,我将在Elixir/Erlang中使用。有一些C方法可以接受和返回,包括通过out参数,并涉及std库中的指针、数据结构或库,如:元组、向量、优先级队列、位集等等。还有接受或返回泛型的方法。或者我自己定制的数据结构。
如何导出此类方法?

template<class T1>
  std::array<MyStruc1, 24> my_func(
    const T1& a1,
    int b1,
    int c1,
    unordered_map<MyStruc1, double>& d1,
    unordered_map<MyStruc2, int>* e1=nullptr) {

    ///////
  }

我熟悉并找到了转换简单结构的示例:char *,仅限简单结构和基本类型。

xriantvc

xriantvc1#

In Erlang, types are what are defined in here . Internal Erlang and C/C++ std representations do not match, you cannot return a, for example, int64_t from C and use it directly from Erlang.
Same for complex structures, is PrioryQueue an Erlang's list() or a {list(), pos_integer()} ?
This means that you need to transform types back and forth, using the enif_get_* and enif_make_*erl_nif functions. For really complex structures this may be tedious, so you really need to consider if it wouldn't be enough using resource objects.
Resource objects are just pointers to memory, and thus, opaque for Erlang. You can have this opaque hold the pointer to the priority queue memory and include methods to put/2 and get/2 Erlang terms to the queue.

Why are the functions from erl_nif required?

Erlang has dynamic typing, where each reference held by a variable includes its type (either in the value for the immediate terms, or in the reference for the referenced terms), while C/C++ have static typing, where the variable is the one that states the type only at compile time.
For C/C++, 0xfabada could be an int , uint , a char* , a void* pointing to your custom structure...
Other reasons for the representations not to match include:

  1. Erlang's integers have variable size
  2. Erlang terms are tagged (some bits of the reference indicate the type)
  3. The closest thing to an atom in C/C++ is an enum, and they are quite different
  4. Binaries (both short an long binaries) and subbinaries
  5. Memory management ... and so on.

相关问题