perl C/C++ 扩展(三)
第三讲
扩展库使用c++实现,在调用函数后,返回对象变量,perl 能正确使用所有对象成员
使用h2xs 命令生成初始文件
h2xs -A -n three_test
登录目录
cd three_test
c++ 头文件
#ifndef INCLUDED_DUCK_H
#define INCLUDED_DUCK_H 1
#include <string>
using std::string;
class Duck
{
public:
Duck(char*);
char* getName();
void swim();
~Duck(){}
private:
bool swimming;
string name;
};
#endif /* INCLUDED_DUCK_H */
c++程序代码
#include "Duck.h"
#include <cstdio> using namespace std; Duck::Duck(char* n) :
swimming(false), name(n)
{
}
const char* Duck::getName()
{
return name.c_str();
}
void Duck::swim()
{
if (!swimming)
{
printf("%s, ok .. go swimming\n", name.c_str());
swimming = true;
}
else
{
printf("%s is already swimming , stop\n", name.c_str());
swimming = false;
}
return;
}
使用g++编译成动态库
g++ -g -Wall -fpic -shared -o libduck.so Duck.cpp
将libduck.so 文件与Duck.h 文件拷贝到 three_test 目录下
cp libduck.so three_test;
cp Duck.h three_test;
XS是一种用于描述接口的文件格式,当我们希望把我们的C/C++库映射成Perl的package时,需要在一个.xs文件中描述接口的映射。另外,我们还需要进行数据类型的映射,下文会提到 perlobject.map文件的使用。
perlobject.map 内容:(原文件地址:http://cpansearch.perl.org/src/ELEONORA/text_hunspell_1.3/perlobject.map)
# "perlobject.map" Dean Roehrich, version
#
# TYPEMAPs
#
# HV * -> unblessed Perl HV object.
# AV * -> unblessed Perl AV object.
#
# INPUT/OUTPUT maps
#
# O_* -> opaque blessed objects
# T_* -> opaque blessed or unblessed objects
#
# O_OBJECT -> link an opaque C or C++ object to a blessed Perl object.
# T_OBJECT -> link an opaque C or C++ object to an unblessed Perl object.
# O_HvRV -> a blessed Perl HV object.
# T_HvRV -> an unblessed Perl HV object.
# O_AvRV -> a blessed Perl AV object.
# T_AvRV -> an unblessed Perl AV object. TYPEMAP HV * T_HvRV
AV * T_AvRV ######################################################################
OUTPUT # The Perl object is blessed into 'CLASS', which should be a
# char* having the name of the package for the blessing.
O_OBJECT
sv_setref_pv( $arg, CLASS, (void*)$var ); T_OBJECT
sv_setref_pv( $arg, Nullch, (void*)$var ); # Cannot use sv_setref_pv() because that will destroy
# the HV-ness of the object. Remember that newRV() will increment
# the refcount.
O_HvRV
# "perlobject.map" Dean Roehrich, version
#
# TYPEMAPs
#
# HV * -> unblessed Perl HV object.
# AV * -> unblessed Perl AV object.
#
# INPUT/OUTPUT maps
#
# O_* -> opaque blessed objects
# T_* -> opaque blessed or unblessed objects
#
# O_OBJECT -> link an opaque C or C++ object to a blessed Perl object.
# T_OBJECT -> link an opaque C or C++ object to an unblessed Perl object.
# O_HvRV -> a blessed Perl HV object.
# T_HvRV -> an unblessed Perl HV object.
# O_AvRV -> a blessed Perl AV object.
# T_AvRV -> an unblessed Perl AV object. TYPEMAP HV * T_HvRV
AV * T_AvRV ######################################################################
OUTPUT # The Perl object is blessed into 'CLASS', which should be a
# char* having the name of the package for the blessing.
O_OBJECT
sv_setref_pv( $arg, CLASS, (void*)$var ); T_OBJECT
sv_setref_pv( $arg, Nullch, (void*)$var ); # Cannot use sv_setref_pv() because that will destroy
# the HV-ness of the object. Remember that newRV() will increment
# the refcount.
O_HvRV
$arg = sv_bless( newRV((SV*)$var), gv_stashpv(CLASS,) ); T_HvRV
$arg = newRV((SV*)$var); # Cannot use sv_setref_pv() because that will destroy
# the AV-ness of the object. Remember that newRV() will increment
# the refcount.
O_AvRV
$arg = sv_bless( newRV((SV*)$var), gv_stashpv(CLASS,) ); T_AvRV
$arg = newRV((SV*)$var); ######################################################################
INPUT O_OBJECT
if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) )
$var = ($type)SvIV((SV*)SvRV( $arg ));
else{
warn( \"${Package}::$func_name() -- $var is not a blessed SV reference\" );
XSRETURN_UNDEF;
} T_OBJECT
if( SvROK($arg) )
$var = ($type)SvIV((SV*)SvRV( $arg ));
else{
warn( \"${Package}::$func_name() -- $var is not an SV reference\" );
XSRETURN_UNDEF;
} O_HvRV
if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVHV) )
$var = (HV*)SvRV( $arg );
else {
warn( \"${Package}::$func_name() -- $var is not a blessed HV reference\" );
XSRETURN_UNDEF;
} T_HvRV
if( SvROK($arg) && (SvTYPE(SvRV($arg)) == SVt_PVHV) )
$var = (HV*)SvRV( $arg );
else {
warn( \"${Package}::$func_name() -- $var is not an HV reference\" );
XSRETURN_UNDEF;
} O_AvRV
if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVAV) )
$var = (AV*)SvRV( $arg );
else {
warn( \"${Package}::$func_name() -- $var is not a blessed AV reference\" );
XSRETURN_UNDEF;
} T_AvRV
if( SvROK($arg) && (SvTYPE(SvRV($arg)) == SVt_PVAV) )
$var = (AV*)SvRV( $arg );
else {
warn( \"${Package}::$func_name() -- $var is not an AV reference\" );
XSRETURN_UNDEF;
}
将文件perlobject.map 拷贝到 three_test 目录下
cp perlobject.map three_test
增加一个Duck类型,保存在文件typemap
touch three_test/typemap
typemap 文件内容
TYPEMAP
Duck* O_OBJECT
修改Makefile.PL 文件
#use 5.014002;
use ExtUtils::MakeMaker;
$CC = 'g++';
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
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']
);
注意,红色部分为增加会修改内容,特别需要指出的是,第一行use 5.014002; 一定需要注释,否则无法正确生成makefile
修改部分,主要是指定编译使用g++
修改three_test.xs 文件
#ifdef __cplusplus
extern "C"{
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#ifdef __cplusplus
}
#endif
#include "ppport.h"
#include "Duck.h"
using namespace std; MODULE = three_test PACKAGE = three_test Duck*
Duck::new(char * name) char*
Duck::getName() void
Duck::swim() void
Duck::DESTROY()
红色部分为增加内容
编译并安装
perl Makefile.PL
make
make install
编写一个perl 测试程序 test.pl
use three_test;
my $duck = new three_test("Dan");
my $name = $duck->getName();
$duck->swim();
$duck->swim();
print "$name\n";
执行
perl test.pl
输出:
Dan, ok .. go swimming
Dan is already swimming , stop
Dan
正确调用了C++的库
参考文章:
http://chunyemen.org/archives/493
http://www.johnkeiser.com/perl-xs-c++.html
官方文档:http://perldoc.perl.org/perlxs.html#NAME
perl C/C++ 扩展(三)的更多相关文章
- perl C/C++ 扩展(五)
perl 的C++扩展,返回值为自定义类型. 在 perl C/C++扩展(三) 中,我已经介绍了,如何让perl 认识 c++的类,但是前面的介绍中,包括我参考的博客http://chunyemen ...
- perl C/C++ 扩展(四)
在前面三篇博客中,我们了解到如何使用c/c++ 扩展自己的perl 库,但是博主在学习过程中,对动态库或静态库的加载不是十分了解,后来自己又细挖一下.后来就有了这篇博文,再后来,没有再后来了,囧!! ...
- 手把手教你开发Chrome扩展三:关于本地存储数据
手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发Chrome扩展二:为html添加行为 手把手教你开发Chrome扩展三:关于本地存储数据 HTML5 ...
- perl C/C++ 扩展(二)
第二讲perl 加载c/c++的库 先通过h2xs 创建一个新的工程 h2xs -A -n two_test 进入目录 cd two_test 创建一个mylib文件夹,存放静态库 mkdir myl ...
- puppet 横向扩展(三)
Table of Contents 1. 概述 2. 实验环境 3. 实验步骤 3.1. 机器B 的配置 3.2. 机器A 的配置 3.3. 测试配置结果 概述 横向扩展实验之三 – 将CA 认证服务 ...
- perl C/C++ 扩展(一)
通过h2xs 中间件,我们可以快速的使用c或则C++ 库来实现perl 扩展功能 第一讲:跑通hello world 程序******************************我们使用命令:h2 ...
- Perl中的正则表达式
转自:http://c20031776.blog.163.com/blog/static/684716252013624383887/ Perl 程序中,正则表达式有三种存在形式 分别是 (1 模式匹 ...
- (转载)CSV 文件处理 PERL
http://cn.perlmaven.com/how-to-read-a-csv-file-using-perl http://search.cpan.org/~hmbrand/Text-CSV_X ...
- Perl 语法 - 基础
perl语言的核心是正则表达式,在文本处理上非常有优势,与python类似,但语法不同,perl的语法很灵活,用多了才会觉得好用. 常用知识点总结: perl语法类似于C语言(perl源于Unix), ...
随机推荐
- Google Guava之Optional优雅的使用null
为什么使用optional 使用Optional<T>除了简化粗鲁的if(null == object).降低函数的复杂度.增加可读性之外,它是一种傻瓜式的防护,Optional<T ...
- 给js设定一个统一的入口
javascript是种脚本语言,浏览器下载到哪儿就会运行到哪儿,这样的特性会为编程提供方便,但也easy使程序过于凌乱.支离破碎. js从功能上能够分为两大部分--框架部分和应用部分,框架部分提供的 ...
- java URI 编码解码
import java.io.UnsupportedEncodingException; /** * url转码.解码 */ public class UrlUtil { private final ...
- ThinkPHP 静态页缓存
通过对ThinkPHP的学习,记录下静态页的缓存步骤,以便以后查阅: 1.配置配置文件/Admin/Conf/config.php代码如下: /*静态缓存*/ 'HTML_CACHE_ON'=> ...
- 上传图片 ajax input type="file" 兼容 ie chroem 火狐
上传图片,转载请注明出处!!! 兼容 ie chroem 火狐 html: <div id="uploadForm"> <input id="file& ...
- 详细的解说public,protected,Default和private的权限问题
详细的解说public,protected,Default和private的权限问题 让人更好的了解public,protected,Default和private他们之间的权限问题,我会做一个直观的 ...
- 001 - 配置Pycharm的字体大小
本文记录的是Pycharm2017年1月版本 1 配置代码区的字体大小 位置在 File -> setting -> Editor -> Color&Fonts -> ...
- ORA-12547: TNS:lost contact
碰到这个ORA-12547: TNS:lost contact的问题,翻了很多资料和METALINK,总结了一下原因: 1 是由于rpm包没有安装,对于我们的生产环境,此包是安装的. admin@p1 ...
- java并发之阻塞队列LinkedBlockingQueue与ArrayBlockingQueue
Java中阻塞队列接口BlockingQueue继承自Queue接口,并提供put.take阻塞方法.两个主要的阻塞类实现是ArrayBlockingQueue和LinkedBlockingQueue ...
- HDU3065(AC自动机入门题)
病毒侵袭持续中 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...