[erlang-questions] Adding a NIF to prim_file

Andre Nathan andre@REDACTED
Sun Apr 28 22:59:34 CEST 2019


Hi

I'm trying to figure out how to add a NIF to the prim_file module. To 
try to get it working, I'm just trying to add an existing function under 
a different name:

In prim_file_nif.c I added the lines below:

WRAP_FILE_HANDLE_EXPORT(my_truncate_nif)

static ErlNifFunc nif_funcs[] = {
   ...
   {"my_truncate_nif", 1, my_truncate_nif, ERL_NIF_DIRTY_JOB_IO_BOUND},
   ...
};

Then I copied truncate_nif_impl and renamed the copy to 
my_truncate_nif_impl.


In prim_file.erl I copied the truncate function, renamed the copy to 
my_truncate and changed it to call my_truncate_nif instead of 
truncate_nif. Then I added

my_truncate_nif(_FileRef) ->
   erlang:nif_error(undef).

However, when I try to build OTP, I get this error:

(no logger present) unexpected logger message: {log,error,"Error in 
process ~p with exit 
value:~n~p~n",[<0.0.0>,{{badmatch,{error,{bad_lib,"Function not found 
prim_file:my_truncate_nif/1"}}},[{prim_file,on_load,0,[]},{erl_init,start,2,[]}]}],#{error_logger=>#{emulator=>true,tag=>error},gl=><0.0.0>,pid=><0.0.0>,time=>1556484838271817}}

Is there anything else I have to do to allow the new function to be 
detected? I couldn't find any other references to truncate_nif that I 
could replicate.

The full diff is pasted below.

Thanks,
Andre


diff --git a/erts/emulator/nifs/common/prim_file_nif.c 
b/erts/emulator/nifs/common/prim_file_nif.c
index 3df04e42e2..61a9b70679 100644
--- a/erts/emulator/nifs/common/prim_file_nif.c
+++ b/erts/emulator/nifs/common/prim_file_nif.c
@@ -162,6 +162,7 @@ WRAP_FILE_HANDLE_EXPORT(allocate_nif)
  WRAP_FILE_HANDLE_EXPORT(advise_nif)
  WRAP_FILE_HANDLE_EXPORT(get_handle_nif)
  WRAP_FILE_HANDLE_EXPORT(ipread_s32bu_p32bu_nif)
+WRAP_FILE_HANDLE_EXPORT(my_truncate_nif)

  static ErlNifFunc nif_funcs[] = {
      /* File handle ops */
@@ -174,6 +175,7 @@ static ErlNifFunc nif_funcs[] = {
      {"seek_nif", 3, seek_nif, ERL_NIF_DIRTY_JOB_IO_BOUND},
      {"sync_nif", 2, sync_nif, ERL_NIF_DIRTY_JOB_IO_BOUND},
      {"truncate_nif", 1, truncate_nif, ERL_NIF_DIRTY_JOB_IO_BOUND},
+    {"my_truncate_nif", 1, my_truncate_nif, ERL_NIF_DIRTY_JOB_IO_BOUND},
      {"allocate_nif", 3, allocate_nif, ERL_NIF_DIRTY_JOB_IO_BOUND},
      {"advise_nif", 4, advise_nif, ERL_NIF_DIRTY_JOB_IO_BOUND},

@@ -721,6 +723,16 @@ static ERL_NIF_TERM sync_nif_impl(efile_data_t *d, 
ErlNifEnv *env, int argc, con
      return am_ok;
  }

+static ERL_NIF_TERM my_truncate_nif_impl(efile_data_t *d, ErlNifEnv 
*env, int argc, const ERL_NIF_TERM argv[]) {
+    ASSERT(argc == 0);
+
+    if(!efile_truncate(d)) {
+        return posix_error_to_tuple(env, d->posix_errno);
+    }
+
+    return am_ok;
+}
+
  static ERL_NIF_TERM truncate_nif_impl(efile_data_t *d, ErlNifEnv *env, 
int argc, const ERL_NIF_TERM argv[]) {
      ASSERT(argc == 0);

diff --git a/erts/preloaded/src/prim_file.erl 
b/erts/preloaded/src/prim_file.erl
index 1aa5d85c64..e350cd9a19 100644
--- a/erts/preloaded/src/prim_file.erl
+++ b/erts/preloaded/src/prim_file.erl
@@ -22,7 +22,7 @@
  -export([on_load/0]).

  -export([open/2, close/1,
-         sync/1, datasync/1, truncate/1, advise/4, allocate/3,
+         sync/1, datasync/1, truncate/1, my_truncate/1, advise/4, 
allocate/3,
           read_line/1, read/2, write/2, position/2,
           pread/2, pread/3, pwrite/2, pwrite/3]).


@@ -242,6 +242,15 @@ truncate(Fd) ->
          error:badarg -> {error, badarg}
      end.

+my_truncate(Fd) ->
+    try
+        #{ handle := FRef } = get_fd_data(Fd),
+        reset_write_position(Fd),
+        my_truncate_nif(FRef)
+    catch
+        error:badarg -> {error, badarg}
+    end.
+
  advise(Fd, Offset, Length, Advise) ->
      try
          #{ handle := FRef } = get_fd_data(Fd),
@@ -493,6 +502,8 @@ allocate_nif(_FileRef, _Offset, _Length) ->
      erlang:nif_error(undef).
  truncate_nif(_FileRef) ->
      erlang:nif_error(undef).
+my_truncate_nif(_FileRef) ->
+    erlang:nif_error(undef).
  get_handle_nif(_FileRef) ->
      erlang:nif_error(undef).
  delayed_close_nif(_FileRef) ->



More information about the erlang-questions mailing list