0

我正在关注 Erlang C Nodes 教程,并试图对 libXl C 库进行包装调用。在我的 C 节点中,创建一个 BookHandle 并将其作为一个消息调用的响应传递。

BookHandle book = xlCreateBook();
resp = erl_format("{ok, ~w}", erl_mk_binary(book, sizeof book));
erl_send(fd, fromp, resp);

我的问题是我可以使用该响应向具有相同对象的 C 节点发送另一条消息吗?例如发送

{any, 'c1@CST1'} ! {self(), {step2,Result}}, 

并在 C 节点中有类似下面的代码来获取传递的 BookHandle

if (strncmp(ERL_ATOM_PTR(fnp), "step2", 3) == 0) {
    BookHandle book = (BookHandle)ERL_BIN_PTR(argp);
    xlBookLoad(book, "example.xls");
}

这样的事情是否可能,或者为特定功能创建包装器需要在每次向 C 节点发送消息时创建 BookHandle。

对不起,如果这没有任何意义,我对这一切都是新手。

4

1 回答 1

0

xlCreateBook()返回一个指针(BookHandle实际上是指向 C++ 对象的指针Book)。因此,您的代码将此指针序列化为 Erlang 二进制文件(根据您的架构,可能长 4 或 8 个字节),并在从 Erlang 节点传回时将其反序列化。

这基本上有效

但是,它有以下两个缺点:

  • 从技术上讲, Erlang 节点可以将任何指针传递给您的 C 节点,甚至是不指向真实Book结构的指针。这可能会导致崩溃或更糟糕的是,数据损坏。
  • 指针可能会丢失(通常是处理这本书的 Erlang 进程死亡),这将在您的 C 节点中产生内存泄漏(因为Book永远不会被释放)。

出于这个原因,无状态 API 设计会更可取,尽管它最终可能会更复杂,特别是如果您希望 Erlang 代码对Book结构进行操作。

或者,您可以维护一个列表BookHandle并传递对该列表中项目的引用(如您当前所做的那样,索引或指针本身,但在未序列化时检查它确实在列表中)。这将解决第一个问题。

第二个问题更棘手。一个解决方案是链接负责给定的 Erlang 进程,并在该进程退出时Book删除该进程。Book不幸的是,用于链接的 API 不存在于 C 端。所以你需要从 Erlang 端进行链接(或者只是尝试禁用的 C 代码来发送 LINK 和 UNLINK 消息)。C 节点应该将每个分配的 Book 与它们各自的 Erlang pid 所有者相关联,如果它收到一个表明所有者进程死亡的 EXIT 消息,则释放这些指针。

附带说明一下,使用 Erlang 生成 XLSX 文件(Office Open XML)非常容易,并且不需要外部库。

于 2014-11-19T10:21:02.323 回答