[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