设为首页 收藏本站
查看: 1281|回复: 0

[经验分享] 将Perl解释器嵌入应用程序中,扩展功能

[复制链接]

尚未签到

发表于 2015-12-27 16:43:16 | 显示全部楼层 |阅读模式
  summary:
本文讲述在应用程序中应嵌入Perl解释器的方法和理由
  
如果系统需要提供扩展性,让用户可以轻松的加入一些对自己很有用的功能,
在应用程序中嵌入一个解释器无疑是最好的选择,你当然可以提供API让用户扩展,
但解释型语言简单易用,一般都带有自动垃圾收集,对用户更合适。
这个解释器可以是任何语言的,但以比较流行的语言为最佳,这样用户扩展功能
时比较容易,因为参考资料和能提供帮助的人都比较多。
  近来需要在一个应用中提供一个扩展就是让用户可以写一些算术公式,公式中的
一些变量是应用程序内部的数据,显然公式肯定是千奇百怪的,不可能全在应用程序
内部实现,只能提供一个解释器,来执行这些公式,自己实现不会有什么困难,但
时间和质量将不能取得最佳效果,所以要考虑从Free的软件项目中获益了,除了C++和Lisp,
我最喜欢Perl,因为Perl项目是自由的,而写Perl程序时更自由。
  好了,下面就说说怎样嵌入Perl解释器(也可以嵌入你喜欢的其他语言的解释器,请阅读相关手册),
Perl的手册页:perlembed,perlapi,perlcall,perlguts都是不错的参考资料。
  一,需要的包含文件和导入库文件都在perl的'lib'目录下的'CORE'中,编译时要在最后
加上如下选项:-L"PERL_ROOT/lib/CORE" -lperl58 -I"PERL_ROOT/lib/CORE",
PERL_ROOT请替换为自己的perl根目录。
程序中包含如下代码:
  #include <perl.h> // 放在最后很重要
#include <EXTERN.h>
static PerlInterpreter *my_perl;
  
二,实现构造、初始Perl解释器和析构、清除Perl解释器的两个函数
/*!
   \brief 用来构造Perl解释器
   
   在执行 perl_parse 时,如果直接用perl_parse(my_perl,NULL,0,&arg,NULL); ///< char *arg="";
   会停下等待你输入,使用"-e"就可以避免这个问题了,参见 char* dummyArg[] = {"","-e",""};
*/
void __init_pe()
{
char* dummyArg[] = {"","-e",""};
PERL_SYS_INIT3(NULL, NULL, NULL);
my_perl = perl_alloc();
perl_construct(my_perl);
perl_parse(my_perl, NULL, 3, dummyArg, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_run(my_perl);
}
  /*!
   用来销毁Perl解释器
*/
void __uninit_pe()
{
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
}
  三,执行perl代码,使用的是eval_pv,还有很多种选择,这个是最简单。
将一个perl程序传给eval_pv执行时,主要的是怎样和perl解释器交换数据,
将应用程序中的数据放入perl解释器中,执行perl脚本后,再将结果取出来。
标量(SV)的存和取相对最简单,也是最基础的。数组(AV)和哈希(HV)内部
使用的都是SV。
标量的例子,很简单:
/// $a=3也可以get_sv("a",true)创建出来:
eval_pv("$a=3;$a**=9;$a=log($a);",true); ///< 执行perl程序
std::cout << "a=" << SvIV(get_sv("a",false)) << '\n'; ///< 取出结果
  我主要举个操作perl数组的例子,可以让用户扩展写出算术表达式,对应用程序中的数据进行处理,
要用到的perl API:get_av,av_fill,av_store,newSVnv,av_len,av_fetch,SvOK,SvNV
首先,要将变量的命名规范先处理好,比如参数用a1,a2,a3...,结果用res,这里都是数组,表达式中要符合这个规范,
然后,要将应用程序中的数据,假设为:std::vector<float> res,data1,data2,data3... 存入perl解释器中,
再执行用户的表达式
最后,从perl解释器中获取运算结果
例子:
/// 存储数据data1到perl解释器中,res,data2,data3...方法类似
AV *pAV = get_av( std::string("a1").data(), true ); // 创建参数数组
av_fill(pAV, data1.size());
for(int i=data1.size()-1; i>=0; --i)
{
  SV** pResult = av_store(pAV, i, newSVnv(data1));
  assert(pResult);
}
  /// 执行脚本,外层加上for包装EXPRESSION并替换@为$,可以直接进行向量运算
eval_pv("EXPRESSION", true); ///< EXPRESSION为用户所写的算术表达式

/// 获取结果
AV *pResultAV = get_av("res", false); // 这里不能创建结果数组,必须存在
assert( pResultAV );
  for(int i=res.size()-1; i>=0; --i)
{
  SV** pSV = av_fetch(pResultAV, i, 0);
  assert( pSV && SvOK(*pSV) );
  if ( !pSV || !*pSV )   return;
  res = SvNV(*pSV);
}

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-157102-1-1.html 上篇帖子: perl的一些函数(二) 下篇帖子: Perl 连接 SQL Server(ReShip)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表