How to implement when C funcs returns structure pointer?

I understand that Example structure can be used on elixir thanks to the following code.

#include <erl_nif.h>
typedef struct{
  int data;
} Example;

Example func_a(){
    Example ex;   
    ex.data = 1;
    return ex;
}

ErlNifResourceType* RES_TYPE;
static int load(ErlNifEnv* env){
  int flags = ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER;
  RES_TYPE = enif_open_resource_type(env, "Elixir.Mod", "Example", NULL, flags, NULL);
}
ERL_NIF_TERM nif_func_a(ErlNifEnv* env,int argc,const ERL_NIF_TERM argv[]){
    Example* res_ex;
    ERL_NIF_TERM ret;
    res_ex = enif_alloc_resource(RES_TYPE,sizeof(Example));
    ret = enif_make_resource(env,res_ex);
    enif_release_resource(res_ex);
    *res_ex = func_a();
    return ret;
}

static ErlNifFunc nif_funcs[] = {
  {"func_a",0,"nif_func_a"}
};
ERL_NIF_INIT(Elixir.Mod, nif_funcs, &load,NULL,NULL,NULL);

I have a question. If func_a() changed as follows, how should I write NIF function ?

const Example* func_a(){
  ...
}

Thanks

You cannot. At least not directly. What you need to do is to use NIF resource object.

2 Likes

Thank you so much for reply.
I was thinking how to rewrite the contents of nif_func_a() but, I understand there are not direct solutions…
func_a() returns a pointer to Example structure. Generally, is it impossible to wrap C function which returns address(for example int* xx()) ?

Thanks

I never had to work with NIFs so I’m probably wrong but I would change this line in nif_func_a definition:

*res_ex = func_a();

to something like

Example* res = func_a();
memcpy(res_ex, res, sizeof(Example));
free(res);

And I guess you could avoid the copy if your func_a took a pointer as an argument and wrote the result directly there.

1 Like

Yes. How would anything know when (& even how) to free it?

1 Like

Thanks everyone for replies.
For the time being, I decided to change to a different specification.

Thanks.