免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 13403 | 回复: 3
打印 上一主题 下一主题

[应用] appweb的JavaScript调用C函数的实现过程(以设置eth0 IP地址为例) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-04-02 19:43 |只看该作者 |倒序浏览
上次帖了交叉编译appweb带matrixssl运行在我的ARM9+linux开发板后,有不少CUer对这个东西很感兴趣。今天贴出appweb的独到之处:EJS调用底层的C函数的实现代码:
appweb-src-2.4.1\doc\guide\appweb\users\ejs\extending.html
appweb-src-2.4.1-latest\appweb-src-2.4.1\doc\api\gen\appweb\overview.html

可以结合:   源码\samples\C++\simpleModule以及  源码\samples\C\simpleEsp目录里的文件来学习。

C++ 代码(ethernetModule.cpp):  

  1. #include        "ethernetModule.h"

  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <errno.h>
  6. #include <unistd.h>

  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <netinet/in.h>
  10. #include <arpa/inet.h>

  11. #include <sys/ioctl.h>
  12. #include <net/if.h>


  13. static int set_ipaddr(const int sockfd, const char *ifname, char *ip);
  14. static int set_netmask(const int sockfd, const char *ifname, char *netmask);

  15. int mprEthernetModuleInit(void *handle)
  16. {
  17.         new EthernetModule(handle);
  18.         return 0;
  19. }

  20. EthernetModule::EthernetModule(void *handle) : MaModule("ethernetModule", handle)
  21. {
  22.                //这里将我们的C函数setEthernet()与EJS(Embedded JavaScript)函数setEthernet()绑定,这样我们在ESP就可以调用底层的C函数了。
  23.                 espDefineStringCFunction(0, "setEthernet", setEthernet, 0);   
  24. }

  25. EthernetModule::~EthernetModule()
  26. {
  27. }

  28. int EthernetModule::parseConfig(char *key, char *value, MaServer *server,
  29.         MaHost *host, MaAuth *auth, MaDir* dir, MaLocation *location)
  30. {
  31.         if (mprStrCmpAnyCase(key, "ethernetDirective") == 0)
  32.                 return 1;
  33.         return 0;
  34. }

  35. int EthernetModule::start()
  36. {
  37.         return 0;
  38. }

  39. void EthernetModule::stop()
  40. {
  41. }

  42. /*
  43. * Function                :        Set IP address, netmask for eth1
  44. * Usage                :        setEthernet(ipaddr, netmask);
  45. * Return value        :          MprVar status
  46. */

  47. static int setEthernet(EspRequest *ep, int argc, char **argv)
  48. {
  49.         char                    *ifname="eth1";
  50.         char                    *ip, *netmask;
  51.                int                     sockfd, ret;
  52.                 struct                 in_addr        addr;       
  53.                 MprVar                 status;
  54.                 status = espCreateObjVar("setStatusObj", 0);

  55.                 ip = argv[0];
  56.                 netmask = argv[1];
  57.                
  58.                 if( (ret=inet_pton(AF_INET, ip, &addr)<=0) || (ret=inet_pton(AF_INET, netmask, &addr)<=0) )
  59.                 {   
  60.                         status = mprCreateIntegerVar(0);               
  61.                         goto ret;
  62.                 }

  63.                 if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
  64.                 {   
  65.                         status = mprCreateIntegerVar(0);               
  66.                         goto ret;
  67.                 }

  68.                 if ((!set_ipaddr(sockfd, ifname, ip)) || (!set_netmask(sockfd, ifname, netmask)) )
  69.                 {   
  70.                         status = mprCreateIntegerVar(0);               
  71.                         goto ret;
  72.                 }
  73.                   
  74.                 status = mprCreateIntegerVar(1);
  75.                
  76.                 ret:
  77.                 espSetReturn(ep, status);
  78.                 espDestroyVar(&status);

  79.                 return 0;
  80. }


  81. static int set_ipaddr(const int sockfd, const char *ifname, char *ip)
  82. {
  83.         struct  sockaddr_in     addr;
  84.         struct  ifreq           ifr;
  85.                 int                ret = 1;  //set status:   0->Failture 1->Success

  86.         bzero(&addr, sizeof(addr));
  87.         addr.sin_family = AF_INET;
  88.                 inet_aton(ip,&addr.sin_addr);

  89.         strncpy(ifr.ifr_name, ifname, IFNAMSIZ-1);

  90.         memcpy(&ifr.ifr_addr,(struct sockaddr *)&addr, sizeof(addr));

  91.         if(ioctl(sockfd, SIOCSIFADDR, &ifr) == -1)
  92.                                 ret = 0;

  93.         return ret;
  94. }


  95. static int set_netmask(const int sockfd, const char *ifname, char *netmask)
  96. {
  97.         struct  sockaddr_in     addr;
  98.         struct  ifreq           ifr;
  99.                 int                ret = 1;  //set status:   0->Failture 1->Success

  100.         bzero(&addr, sizeof(addr));
  101.         addr.sin_family = PF_INET;
  102.         inet_aton(netmask,&addr.sin_addr);

  103.         strncpy(ifr.ifr_name, ifname, IFNAMSIZ-1);
  104.         memcpy(&ifr.ifr_netmask,(struct sockaddr *)&addr, sizeof(addr));

  105.         if(ioctl(sockfd, SIOCSIFNETMASK, &ifr) == -1)
  106.                                 ret = 0;

  107.         return ret;
  108. }
复制代码


上层的EJS网页代码(ethernetSet.esp):

  1. <html>
  2.         <head>
  3.                 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  4.                 <title>Set ethernet IP address</title>
  5.       </head>
  6.        
  7.   
  8.         <body>
  9.         <%if(session['username']){%>           //判断用户是否登录,如果登录就显示该页
  10.        
  11.      <div class="mainTitle marginAuto" id="title">Ethernet IP Setting</div>
  12.         <div class="mainBox marginAuto">
  13.                 <div class="mainContent">
  14.                 <div class="innerContent">

  15.                                         <form method="POST" action="@@request['SCRIPT_NAME']" >  //提交表单
  16.                                                 <table class="inputForm" border=0>
  17.                                                         <tr>
  18.                                                                 <td><b>IP Address</b></td>
  19.                                                                 <td><input name="ip" type="text" value="@@form['ip']" onBlur="validIP(this,0);"></td>
  20.                                                         </tr>
  21.                                                         <tr>
  22.                                                                 <td><b>Netmask</b></td>
  23.                                                                 <td><input name="netmask" type="text" value="@@form['netmask']" onBlur="validIP(this,1)"></td>
  24.                                                         </tr>
  25.                                                 </table>
  26.                                                 <input type="submit"  value="Submit">
  27.                                                 <input type="reset" value="Reset">
  28.                                   </form>

  29.                                 <%        
  30.                                         if (request["REQUEST_METHOD"] == "POST")   //处理提交的表单
  31.                                         {
  32.                                                 var ret;
  33. //form['ip']为表单提交的值,并调用上面写的C代码来设置IP地址,这里底层的C函数能返回MprVar(Object)类型值,或string。
  34.                                                 ret = setEthernet(form['ip'], form['netmask']);   
  35.                                                 if(0 == ret)   
  36.                                                         write("Set failure: Make sure the input IP address is a valid IPv4 address.</br>");
  37.                                                 else
  38.                                                 {
  39.                                                         write("The set IP address: " + form['ip'] + "</br>");
  40.                                                         write("The set netmask address: " + form['netmask'] + "</br>");
  41.                                                 }  
  42.                                         }
  43.                                 %>

  44.                  </div>
  45.          </div>
  46.      </div>

  47.         <%
  48.                 }
  49.                 else
  50.                 {
  51.                         redirect("login.esp");  //如果没登录,就转到login.esp去登录。
  52.                 }
  53.         %>               

  54.         </body>
  55. </html>
复制代码



上面的C++函数需要编译成动态库,然后在appweb.conf里加载这个模块,使这个函数作为appweb的一部分,这样方能使用EJS调用底层的C函数。

评分

参与人数 1可用积分 +15 收起 理由
bitmilong + 15 原创内容

查看全部评分

论坛徽章:
0
2 [报告]
发表于 2008-04-02 20:08 |只看该作者
上面只给出了源代码,并没有给出实现的过程,这里还是一道奉上:

在appweb-src-2.4.1\samples\C++\simpleModule 拷贝一份,并更名为ethernetModule,将上面的ethernetModule.cpp 源代码放到该目录下,并将所有文件里的simpleModule改为ethernetModule(注意有大小写)。参考simpleModule改。

然后执行make,如果是交叉编译,他会到找上层Makefile中设置的交叉编译器来进行交叉编译。Make后会得到ethernetModule.so,将其更名为libethernetModule.so并放到appweb指定的动态库路径下,也可以通过LD_LIBRARY_PATH环境变量来指定。

修改appweb.conf (118行左右)为:
LoadModulePath "../lib/arm-atmel-linux/modules"
#这个路径即为appweb寻找动态库的路径,也可以通过LD_LIBRARY_PATH环境变量来指定。

        LoadModule ethernetModule libethernetModule

<if SSL_MODULE>
        LoadModule ssl libsslModule

        <if MATRIXSSL_MODULE>
                LoadModule matrixSsl libmatrixSslModule
        </if>

        <if OPENSSL_MODULE>
                LoadModule openSsl libopenSslModule
        </if>
</if>


重启appweb,这时appweb就会像加载所有其他模块一样(如matrixssl)一样加载我们的ethernetModule.so(可以通过看logs/error.log检查是否加载成功).这样就可以在ethernetSet.esp顺利的调用 ret = setEthernet(form['ip'], form['netmask']);

顺便提一句: appweb和我们的c/c++程序都是运行在同一个进程环境下,这样我们必须保证我们的C/C++代码不能出现任何错误(段错误)导致进程退出。有一次,我就在一行C代码里调用了exit(),结果每导致执行一次该页面,服务器就down掉一次,害得我郁闷了好几天。


PS: 这两天开始移植uclinux到我们的ARM7开发板,发现appweb已经加到uClinux源码包里了。看到appweb是那么的眼熟,寒个先........

[ 本帖最后由 dglwx 于 2008-11-26 08:46 编辑 ]

评分

参与人数 1可用积分 +15 收起 理由
bitmilong + 15 精品文章

查看全部评分

论坛徽章:
0
3 [报告]
发表于 2008-11-25 14:59 |只看该作者
这么好的帖子,居然漏掉了加精华,真是不好意思

感谢分享

论坛徽章:
0
4 [报告]
发表于 2010-07-30 09:50 |只看该作者
您好,我最近在学习appweb,有些问题想请教你一下:
     1.麻烦您说一下esp是什么概念,它是一种脚本语言吗?与ejscript有区别吗?
     2.在esp中内嵌c语言,是可以添加任意功能的c代码程序吗?
麻烦您了,谢谢。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP