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

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

我正在用 C++ 编写一个库,我将在 Elixir/Erlang 中使用它。有接受和 return 的 C++ 方法,包括通过输出参数,并涉及指针、数据结构或来自 std 库的库,例如:元组、向量、优先级队列、位集等。还有接受或 return 泛型的方法。或者我自己的自定义数据结构。

如何导出此类方法?

  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*、仅简单结构和原始类型。

在 Erlang 中,类型是在 here 中定义的。内部 Erlang 和 C/C++ std 表示不匹配,你不能 return a,例如,来自 C 的 int64_t 并直接从 Erlang 使用它。

对于复杂结构也是如此,PrioryQueue 是 Erlang 的 list() 还是 {list(), pos_integer()}?

这意味着您需要使用 enif_get_*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.

来回转换类型

资源对象只是指向内存的指针,因此对于 Erlang 来说是不透明的。您可以让这个不透明保存指向优先级队列内存的指针,并将 put/2get/2 Erlang 术语的方法包含到队列中。

为什么需要 erl_nif 中的函数?

Erlang 具有动态类型,其中变量持有的每个引用都包含其类型(在直接项的值中,或在引用项的引用中),而 C/C++ 具有静态键入,其中变量是仅在编译时声明类型的变量。

对于C/C++,0xfabada可以是intuintchar*void*指向你的自定义结构...

表示不匹配的其他原因包括:

  1. Erlang 的整数大小可变
  2. Erlang 术语被标记(引用的某些位指示类型)
  3. 在C/C++中最接近原子的是枚举,它们有很大的不同
  4. 二进制文件(短二进制文件和长二进制文件)和子二进制文件
  5. 内存管理 ...等等。