erlang判断模块导出函数问题
来源:互联网 发布:单片机推挽输出 编辑:程序博客网 时间:2024/04/28 22:45
erlang本身提供一个接口,可以用来检查模块是否有导出函数,这个接口是erlang:function_exported/3,但是很多时候这个接口无法正常使用。
下面重现一下这个问题:
1> erlang:function_exported(crypto,start,0).false2> crypto:start().ok3> erlang:function_exported(crypto,start,0).true
注意:例子中并不是说一定要crypto:start()才能使用这个函数,只是说这个函数确实存在。
现在,来看下erlang对这个接口的说明:
Returns true if the module Module is loaded and contains an exported function Function/Arity; otherwise false.
Returns false for any BIF (functions implemented in C rather than in Erlang).
换句话说,如果一个模块还没有被加载,就无法使用erlang:function_exported/3函数。很多模块在erlang启动时都没有加载到系统,都是在使用到的时候才加载,所以这个检查导出函数的接口可能会出现错误的结果。
如果要判断模块是否有导出函数,那么,我们可以像下面这么写,就可以正常使用了。
-module(test).-compile(export_all).function_exported(Module, Function, Arity) ->case erlang:module_loaded(Module) oftrue ->next;_ -> code:ensure_loaded(Module)end,erlang:function_exported(Module, Function, Arity).另外,如果模块被改成bif也无法判断了。不过这倒不用太过担心,我们自己写的函数都不会是bif
最后,讨论下erlang:function_exported/3为何只能检查已加载过的模块?
为了实现热更新,新旧代码替换,erlang维护了一个全局哈希表,用于描述模块导出函数信息。那么,只要加载过的模块就会被记录信息到这个哈希表,保存这些信息也要耗费一定的内存开销,而且,哈希算法本身存在冲突的可能性,元素越多,发生冲突的可能性越大,为了解决冲突,还会引入了bucket(哈希桶)或者链表。这样,如果要保证键值分散,就会浪费很多空间,不然又会影响查找效率。
所以,erlang只记录了加载过的模块信息,其他等到使用到的时候再加载。
erlang:function_exported/3是一个bif函数,实现函数可以在erts\emulator\beam\bif.c找到:
BIF_RETTYPE function_exported_3(BIF_ALIST_3){ if (is_not_atom(BIF_ARG_1) || is_not_atom(BIF_ARG_2) || is_not_small(BIF_ARG_3)) { BIF_ERROR(BIF_P, BADARG); } if (erts_find_function(BIF_ARG_1, BIF_ARG_2, signed_val(BIF_ARG_3), erts_active_code_ix()) == NULL) { BIF_RET(am_false); } BIF_RET(am_true);}erts_find_function实现在erts\emulator\beam\export.c中:
/* * Find the export entry for a loaded function. * Returns a NULL pointer if the given function is not loaded, or * a pointer to the export entry. * * Note: This function never returns export entries for BIFs * or functions which are not yet loaded. This makes it suitable * for use by the erlang:function_exported/3 BIF or whenever you * cannot depend on the error_handler. */Export* erts_find_function(Eterm m, Eterm f, unsigned int a, ErtsCodeIndex code_ix){ struct export_templ templ; struct export_entry* ee; ee = hash_get(&export_tables[code_ix].htable, init_template(&templ, m, f, a)); if (ee == NULL ||(ee->ep->addressv[code_ix] == ee->ep->code+3 && ee->ep->code[3] != (BeamInstr) BeamOp(op_i_generic_breakpoint))) { return NULL; } return ee->ep;}这里,export_tables是一个全局变量,还是在export.c,其中,code_ix被用来控制代码版本,有时间的话再讨论erlang热更新机制
static IndexTable export_tables[ERTS_NUM_CODE_IX]; /* Active not locked */所以,erlang:function_exported/3只是去查找导出函数的哈希表,找到返回true,没有就false
参考:http://blog.csdn.net/mycwq/article/details/40663737
2 0
- erlang判断模块导出函数问题
- Erlang基础 - 模块声明、函数导出声明和注释
- Erlang -模块和函数
- erlang list模块函数
- Erlang:第一个Erlang程序,模块,函数
- erlang 模块常用函数总结
- erlang的dict模块函数方法介绍
- erlang的dict模块函数方法介绍
- erlang lists模块函数使用大全
- Erlang 的 dict 模块函数方法介绍
- erlang lists模块函数使用大全
- erlang lists模块函数使用大全
- erlang lists模块函数使用大全
- erlang lists模块函数使用大全
- Erlang(4):模块和函数
- Erlang学习笔记(四)模块与函数
- erlang函数调用中的一些问题
- Erlang基础 - 模块的编译和函数的调用
- 【Linux】Centos 清除KDE桌面
- 多态
- 怎么读C++ Primer
- lua闭合函数
- [wxWidgets]_[初级]_[不常见但实用的类wxStandardPaths]
- erlang判断模块导出函数问题
- Android自定义控件
- 静态库里的静态变量
- linux系统编码及vim编码使用说明
- PHP分页
- 周报--FPGA
- android控制软键盘显示与隐藏
- 循环登录问题
- android/iphone/windows/linux声波通讯库