我有一个nif库,每次重新编译它时,我都必须重新启动shell来重新加载或升级这个库。
这是我的erlang代码:
-module(q4).
-export([init/0]).
-on_load(init/0).
init() ->
erlang:load_nif("./q4_nif", reload).
每次我编译erlang模块时,都会出现以下错误:
`The on_load function for module q4 returned {error,
{upgrade,
"Upgrade not supported by this NIF library."}}`
当我调用init/0
函数时,会出现以下错误:{error,{reload,"Reload not supported by this NIF library."}}
有没有办法在不重新启动shell的情况下解决这个问题并加载新的nif库?
如错误消息所示,您需要在NIF中提供upgrade
函数,该函数在对ERL_NIF_INIT
:的调用中指定
ERL_NIF_INIT(MODULE, ErlNifFunc funcs[], load, reload, upgrade, unload)
升级功能记录在erl_nif
手册页中。
UPDATE找到根本原因
似乎delete
在热重新加载NIF之前必须调用两次这看起来像是erlang错误。
force_upgrade_module(Mod) ->
true == code:purge(Mod),
true == code:delete(Mod),
code:purge(Mod),
code:delete(Mod),
{module,Mod} == code:load(Mod).
即使在ERL_NIF_INIT
中实现upgrade
,仍然存在一些问题,这些问题可能是平台特定的,也可能不是平台特定的。例如,在macOS上:在erlang stub模块中调用load_nif
后,可以随意删除priv/{{module}}.so
,它只会默默地继续成功,而不会真正重新加载NIF.so.