1

I am working on integrating a Third Party C++ API in Elixir using NIFs. Here is the code sample that is shared and is working fine when I run it like a binary.

class Client: public AbstractThirdPartyClient {
  public:
    int ConnectionSuccess(int status) {
       return status;
    }
};

int main () {
  Client *client = new Client;
  ThirdPartyControl *control = new ThirdPartyControl(client, "fully/qualified/path/to/some/config/file");
  return 0;
}

But when I am trying to introduce NIFs converting to a dynamic lib (.so) file, NIF loading fails with seg fault and since ThirdPartyControl class implementation is hidden from me, I am having a hard time figuring out why this is failing.


ERL_NIF_TERM setup(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
  return enif_make_atom(env, "ok");
}

static ErlNifFunc nif_funcs[] = {{"setup", 0, setup}};

int load(ErlNifEnv* caller_env, void** priv_data, ERL_NIF_TERM load_info) {
  try {
    Client *client = new Client;
    /* this line causes seg fault don't know why */
    ThirdPartyControl *control = new ThirdPartyControl(client, (char *)NULL, (char *)"fully/qualified/path/to/some/config/file");
    *priv_data = (void *)control;
  } catch (exception e) {
    return 1;
  }
  return 0;
}

int upgrade(ErlNifEnv* caller_env, void** priv_data, void **old_priv_data, ERL_NIF_TERM load_info) {
  return 0;
}

ERL_NIF_INIT(Elixir.Vendor.Middleware, nif_funcs, load, NULL, upgrade, NULL);
2240
  • 1,547
  • 2
  • 12
  • 30
  • 1
    You could try `strace` on the binary to see which system calls are triggered. I'm not entirely sure about the implications of using `malloc` instead of `enif_alloc` inside the nif, which I guess is what the library is using for the `new` (or some sort of allocator that's unaware of the VM that's running it). – José M May 13 '21 at 13:12
  • 2
    That being said, I strongly recommend against using NIFs for this, as you don't control the implementation and it could potentially exceed the amount of time that any nif should be allowed to run (thus rendering the system irresponsive) or even crash the whole VM. Maybe you could consider [ports](https://erlang.org/doc/reference_manual/ports.html), spawning the library as a separate OS process communicating via `stdin/stdout` – José M May 13 '21 at 13:14

0 Answers0