前几天研究ejabberd时,发现它log模块设置log_level采用动态编译方式,主要是基于dynamic_compile模块实现。于是基于它的动态编译进行了扩展,以到达可以动态代码编译并进行热替换的目的。在某些场合还是很实用的。废话少说,直接贴代码:
此模块需要依赖 ejabberd 里的 dynamic_compile.erl 模块
%%%----------------------------------------------------------------------
%%% 动态编译模块
%%% 将目标模块代码字符串序列,动态编译并加载至运行VM中执行
%%% 动态调用执行,每次动态编译相当于一次热更新替换.
%%% @author angine
%%% 例如:
%%% dynamic_code:c().
%%% mod_code:test().
%%% mod_code:calc_val(10,20).
%%%----------------------------------------------------------------------
-module(dynamic_code).
-export([c/1,fc/1]).
-export([t/0,t1/0]).
-define(Mod_Name, "mod_code").
%% ----------------------------------------------------------------------
%% 动态编译
%% 参数 File 目标源代码文件路径 例如: File = "../ebin/mod_code.erl",
%% ----------------------------------------------------------------------
fc(File) ->
try
{ok,Binary}=file:read_file(File),
% 过滤 回车换行
Bin_Str_Code = binary:replace(Binary, [<<"\r">>], <<>>, [global]),
Str_Code = binary_to_list(Bin_Str_Code),
c(Str_Code)
catch
Type:Error ->
io:format("exception: ~p ~p ~n",[Type,Error])
end.
%% ----------------------------------------------------------------------
%% 动态编译
%% 参数 Str_Code type String 模块源代码 字符串类型
%% ----------------------------------------------------------------------
c(Str_Code) ->
try
{Mod,BinCode} = dynamic_compile:from_string(Str_Code),
io:format("mod name: ~p~n",[Mod]),
code:purge(Mod),
code:load_binary(Mod, tool:to_list(Mod) ++ ".erl", BinCode)
catch
Type:Error ->
io:format("Error compiling logger (~p): ~p~n", [Type, Error])
end.
%% ----------------------------------------------------------------------
%% 动态编译 测试
%% ----------------------------------------------------------------------
t() ->
c(code_src()).
t1() ->
File = "../ebin/mod_code.erl",
fc(File).
%% ----------------------------------------------------------------------
%% 源代码示例
%% ----------------------------------------------------------------------
code_src() ->
"-module(mod_code).
-export([
test/0,
add/2
]).
%% 测试输出
test() -> \"erlang, hello~world~n\" .
%% 计算加
add(A,B) ->
{val,A+B}.
".
可以看到真正的实现其实很简单,动态编译并进行代码版本热替换
{Mod,BinCode} = dynamic_compile:from_string(Str_Code),
code:purge(Mod),
code:load_binary(Mod, tool:to_list(Mod) ++ ".erl", BinCode)
ok,记录下来...方便查阅。