`
cwqcwk1
  • 浏览: 86888 次
文章分类
社区版块
存档分类
最新评论

erlang判断模块导出函数问题

 
阅读更多
erlang本身提供一个接口,可以用来检查模块是否有导出函数,这个接口是erlang:function_exported/3,但是很多时候这个接口无法正常使用。
下面重现一下这个问题:
1> erlang:function_exported(crypto,start,0).
false
2> crypto:start().
ok
3> erlang:function_exported(crypto,start,0).
true
注意:例子中并不是说一定要crypto:start()才能使用这个函数,只是说这个函数确实存在。

现在,来看下erlang对这个接口的说明:
Returns true ifthe module Module is loadedand contains an exported function Function/Arity; otherwise false.
Returns false for anyBIF(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) of
		true ->
			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
分享到:
评论

相关推荐

    erlang两种参数模块化

    在Erlang中,编译单元是模块,每个模块都有一个唯一的名称,并包含多个函数,其中只有被明确标记为可导出的函数才能被其他模块访问。 动态代码替换是Erlang的一个特性,允许在任何时候加载模块的新版本。这使得在不...

    erlang 参考手册 模块部分--自己翻译的中文版

    模块是Erlang程序的基本单位,包含了特性(attribute)和函数(function)声明。下面将详细介绍Erlang模块的规则、特性、预处理以及相关函数。 4.1 模块规则 Erlang的程序源码被划分为多个模块,每个模块由一系列的...

    erlang中文基础教程

    例如,用户可以创建一个模块,定义一个函数来实现某个计算任务,然后在 Erlang Shell 中调用该函数来实现任务。 4. 编译和运行 在 Erlang 中,用户需要编译模块然后才能运行。编译模块可以使用 c() 函数,例如 c...

    erlang 设计指南

    模块间通过导出和导入函数来实现接口交互,便于代码复用和维护。 在分布式系统方面,Erlang节点可以在网络中互相发现并通信,形成一个集群。节点之间的通信几乎透明,允许构建跨越多个物理机器的分布式应用程序。...

    Erlang编程规则——中文翻译版本

    Erlang特殊约定部分主要涉及了模块和函数的定义方式,强调了模块的起始位置应当放置导出函数的声明,以及在模块内部函数的声明应当遵循特定的顺序,从而确保代码的结构性和可读性。在Erlang中,存在一些内置函数...

    erlang趣学指南

    这本书的作者Fred Hébert是一位在一线拥有丰富实战经验的工程师,他通过轻松幽默的文风和清晰的讲解,向读者介绍了Erlang的模块、函数、类型、递归、错误处理、数据结构、并行编程、多处理、事件处理以及Erlang的...

    erlang 中文基础教程

    ### Erlang 中文基础教程:理解Erlang Shell与模块函数 #### 1. Erlang Shell:编程者的交互式环境 Erlang Shell是Erlang编程语言提供的一种交互式编程环境,允许开发者直接在命令行中编写、执行Erlang代码并观察...

    英雄远征源码[erlang]

    Erlang是一种为并发、容错和实时系统设计的函数式编程语言,以其在高可用性和可扩展性上的优势,常被用于构建大规模、分布式的游戏服务器。 1. **Erlang语言基础** Erlang是一种动态类型的并发编程语言,源于瑞典...

    xiandiao_erlang_Erlang课后习题_

    5. **模块化编程**:Erlang的模块系统可以帮助组织代码,习题可能要求学习者将功能分解到多个模块中,提高代码的可重用性和可读性。 6. **性能优化**:通过解决实际问题,学习者可以学习到如何有效地利用Erlang的...

    erlang-bblm:BBEdit 的 Erlang 语言模块

    BBEdit 的 Erlang 语言模块 v1.4, (2018/01/14) Erlang... 在 OTP 模块中键入对函数的调用时,Erlang 语言模块显示实际的参数顺序、参数名称以及文档中描述的返回值。下载可以从GitHub下载二进制文件: : 安装要安装该

    erlang编程 Introducing Erlang

    Erlang是一种函数式编程语言,由爱立信在1986年开发,主要用于构建高可用性、容错性和并发性的分布式系统。"Introducing Erlang"是Simon St. Laurent撰写的一本入门级教程,旨在帮助初学者理解和掌握Erlang的核心...

    erlang深度分析

    - **模块与函数**:了解Erlang的模块化结构,以及如何定义和导出函数。 - **错误处理与日志记录**:学习Erlang的异常处理机制,以及如何有效地记录和调试问题。 - **模式匹配与函数选择**:掌握如何利用模式匹配来...

    Erlang 中的Module级别热部署

    在Erlang中,模块是代码的基本单元,包含函数定义和其他声明。当一个模块被加载到Erlang虚拟机(VM)时,它的代码会被编译并驻留在内存中。热部署就是指在不重启VM或应用程序的情况下,更新这些驻留在内存中的模块...

    erlang25.0 windows版本

    2. **API更新**:可能对Erlang的内置函数或模块进行增强,提供新的功能或修复已知问题。 3. **兼容性提升**:与先前版本相比,25.0可能增强了与其他软件或框架的兼容性。 4. **错误修复**:解决上一版本中的已知问题...

    [Erlang程序设计]源代码

    **五、模块与导出** Erlang的模块系统是组织代码的关键。在源代码中,你将看到`module/0`声明,定义了模块的名称,以及`export/1`声明,列出了对外公开的函数。这种模块化设计有助于代码的复用和维护。 **六、 OTP...

    Programming Erlang

    此外,Erlang的模块和导出机制也是重要的部分。书中将解释如何组织代码为模块,以及如何通过导出来共享功能。Erlang的热加载特性使得代码更新和调试变得非常方便,这对于持续运行的系统尤其有用。 在分布式编程方面...

    erlang资源

    3. **过程和模块**:Erlang的组织方式,包括如何定义和调用函数,以及模块的使用。 4. **错误调试**:Erlang的错误处理机制,如shell的使用、日志和调试工具。 5. **REPL(Read-Eval-Print Loop)**:Erlang shell...

    Erlang趣学指南

    (494页带目录的高清扫描版) 这是一本讲解Erlang编程语言的入门指南,内容通俗...内容涉及模块、函数、类型、递归、错误和异常、常用数据结构、并行编程、多处理、OTP、事件处理,以及所有Erlang的重要特性和强大功能。

    erlang9.rar

    Erlang还有强大的模块系统,每个文件对应一个模块,模块内包含函数定义。 OTP库提供了许多实用的模块,如gen_server、gen_event和gen_fsm,这些都是Erlang并发编程的基础。 总而言之,Erlang9.rar是一个包含Erlang/...

Global site tag (gtag.js) - Google Analytics