简体   繁体   中英

Casting complex, non-primitive C++ data types into Erlang/Elixir format, to export methods using NIF

I'm writting a library in C++ which I'll use in Elixir/Erlang. There're C++ methods that accept and return, including via out parameters, and involving pointers, data structures or library from std library such as: tuples, vectors, priority queues, bitsets and so forth. And also methods that accept or return generics. Or my own custom data structures.

How do I export such methods?

  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) {

    ///////
  }

I'm familiar with, and have found examples, converting simple structures: char*, simple structs and primitive types only.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM