前几天研究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,记录下来...方便查阅。