zoukankan      html  css  js  c++  java
  • perl C/C++ 扩展(四)

    在前面三篇博客中,我们了解到如何使用c/c++ 扩展自己的perl 库,但是博主在学习过程中,对动态库或静态库的加载不是十分了解,后来自己又细挖一下。后来就有了这篇博文,再后来,没有再后来了,囧!!

    我们先来看看 perl c/c++ 扩展(二)中的 Makefile.PL

    WriteMakefile(
        NAME              => 'two_test',
        VERSION_FROM      => 'lib/two_test.pm', # finds $VERSION
        PREREQ_PM         => {}, # e.g., Module::Name => 1.1
        ($] >= 5.005 ?     ## Add these new keywords supported since 5.005
          (ABSTRACT_FROM  => 'lib/two_test.pm', # retrieve abstract from module
           AUTHOR         => 'root <root@>') : ()),
        LIBS              => [''], # e.g., '-lm'
        DEFINE            => '', # e.g., '-DHAVE_SOMETHING'
        INC               => '-I.', # e.g., '-I. -I/usr/include/other'
       # Un-comment this if you add C files to link with later:
        # OBJECT            => '$(O_FILES)', # link all the C files too
        MYEXTLIB => 'mylib/libchen.a'
    ); 

    注意:

    我们第一次写时,是没有填写 LIBS 与 INC 字段的,但是我们增加了一个 MYEXTLIB 的字段,指定我们要增加‘mylib/libchen.a'的静态库

    由于在perl c/c++ 扩展(三)中,我们是使用了***.so 动态库来编译,而且也能正常工作,所以我就想,在(二)里,肯定也能调用动态库。

    于是对原程序改动了一下,编译出一个libchen.so的文件,放在mylib/ 目录下。

    修改一下Makefile.PL 脚本

    MYEXTLIB => 'mylib/libchen.so'

    还是使用之前的命令

    perl Makefile.Pl
    make
    make install

    编译通过,但在运行测试脚本时出错,说是找不到动态库。

    这个问题简单,给环境变量LD_LIBRARY_PATH 添加一下libchen.so路径即可。再次运行测试脚本,通过。

    由于需要添加环境变量这个细节又引起我的注意,在使用中,我知道perl c/c++ 扩展(三) 的编译方法不依赖环境变量的,也就是说,无论切换到什么窗口都可成功运行测试脚本。

    我们来看看(三)是怎么写Makefile.PL的

    WriteMakefile(
        NAME              => 'three_test',
        VERSION_FROM      => 'lib/three_test.pm', # finds $VERSION
        PREREQ_PM         => {}, # e.g., Module::Name => 1.1
        ($] >= 5.005 ?     ## Add these new keywords supported since 5.005
          (ABSTRACT_FROM  => 'lib/three_test.pm', # retrieve abstract from module
           AUTHOR         => 'root <root@>') : ()),
        LIBS              => ['-L./ -lduck'], # e.g., '-lm'
        DEFINE            => '', # e.g., '-DHAVE_SOMETHING'
        'CC'              => $CC,
        'LD'              => '$(CC)',
        INC               => '-I.', # e.g., '-I. -I/usr/include/other'
       # Un-comment this if you add C files to link with later:
        # OBJECT            => '$(O_FILES)', # link all the C files too
    
        'XSOPT'           => '-C++',
        'TYPEMAPS'        => ['perlobject.map']
    );

    我们看到,除了新增了XSOPT  TYPEMAPS  CC  LD字段外,还修改了 LIBS  INC字段。

    而且LIBS 字段的内容就是g++ 的lib 库,INC 字段就是头文件的地址。

    所以我们将(二) 的Makefile.PL修改一下,变成

    WriteMakefile(
        NAME              => 'two_test',
        VERSION_FROM      => 'lib/two_test.pm', # finds $VERSION
        PREREQ_PM         => {}, # e.g., Module::Name => 1.1
        ($] >= 5.005 ?     ## Add these new keywords supported since 5.005
          (ABSTRACT_FROM  => 'lib/two_test.pm', # retrieve abstract from module
           AUTHOR         => 'root <root@>') : ()),
        LIBS              => ['-Lmylib -lchen'], # e.g., '-lm'
        DEFINE            => '', # e.g., '-DHAVE_SOMETHING'
        INC               => '-Imylib', # e.g., '-I. -I/usr/include/other'
       # Un-comment this if you add C files to link with later:
        # OBJECT            => '$(O_FILES)', # link all the C files too
        #MYEXTLIB => 'mylib/libchen.so'
    );

    修改了 LIBS  INC 字段,指定动态库的地址为-Lmylib,使用chen的库-lchen

    INC字段写chen.h 头文件的地址。

    注意,这时候,我们还是沿用libchen.so的动态库。

    编译并按装

    perl Makefile.PL 
    make
    make install

    运行测试脚本,OK

    切换一个窗口(等于没有执行export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/learn/perl/two_test/mylib) ,再运行测试脚本,依然OK。

    但是当我们将mylib目录下的动态库改名,变成libchen.so.bak。再运行测试脚本,失败,报错说找不到libchen.so的库

    错误信息:/usr/local/lib/perl/5.14.2/auto/two_test/two_test.so' for module two_test: libchen.so: 无法打开共享对象文件: 没有那个文件或目录 at /usr/share/perl/5.14/XSLoader.pm line 71

    到这里,我们就可以知道了,实质上在LIBS 字段写上库名,应该是在生成Makefile时,将绝对路径包含了,并且自动添加到环境变量了,所以使用动态库生成的perl 扩展,运行环境都需要将动态库加入环境变量里。

    上面的测试,扩展包还需要运行环境有动态库,对于移植性来说,多有不便。所以我们还是希望使用静态库编译。

    方法很简单,只要将libchen.so 动态库替换成 libchen.a 静态库,在重新编译扩展包就好了。

    perl Makefile.PL 
    make
    make install

    这次,无论你怎造,perl 的测试程序都能正确运行。

    我们再回头看看(二)的Makefile.PL

    WriteMakefile(
    NAME => 'two_test',
    VERSION_FROM => 'lib/two_test.pm', # finds $VERSION
    PREREQ_PM => {}, # e.g., Module::Name => 1.1
    
    ($] >= 5.005 ? ## Add these new keywords supported since 5.005
    (ABSTRACT_FROM => 'lib/two_test.pm', # retrieve abstract from module
    AUTHOR => 'root <root@>') : ()),
    LIBS => [''], # e.g., '-lm'
    DEFINE => '', # e.g., '-DHAVE_SOMETHING'
    INC => '-I.', # e.g., '-I. -I/usr/include/other'
    # Un-comment this if you add C files to link with later:
    # OBJECT => '$(O_FILES)', # link all the C files too
    MYEXTLIB => 'mylib/libchen.a'
    );

    它也是使用了libchen.a静态库,经过测试,运行时也能不再依赖库了。

    总结:

    无论是使用MYEXTLIB 字段,还是通过指定LIBS  INC来指向库文件,只要是使用静态库编译,扩展包都能脱离库的依赖。

  • 相关阅读:
    编程之美:位运算应用集萃
    【总结系列】互联网服务端技术体系:高性能之缓存面面观
    【总结系列】互联网服务端技术体系:高性能之并发(Java)
    【总结系列】互联网服务端技术体系:高性能之数据库索引
    【总结系列】互联网服务端技术体系:可扩展之数据分区
    一道关于二叉树的字节面试题的思考
    python基础之range()函数和random模块
    记录下第一次参加leetcode 周赛
    几种方法实现“反转字符串”
    c# 自动更新程序
  • 原文地址:https://www.cnblogs.com/chenfool/p/3897799.html
Copyright © 2011-2022 走看看