本文通过在ruby下使用SWIG封装libcurl来简要描述如何通过SWIG来扩展ruby。
关于SWIG的入门使用可参见 使用SWIG扩展ruby性能
关于SWIG:
SWIG全称为 Simplified Wrapper and Interface Generator,通过swig可以方便快捷的使用c/c++扩展php, ruby等语言以提高性能或满足其它用途。
关于libcurl:
libcurl是一个著名的http/ftp库,通过libcurl可能轻松通过http/ftp协议访问网络。
流程:

相关文件:
SWIG的封装文件 curl.i
%module curl
%{
#include <curl/curl.h>
%}
/* type definations */
typedef int CURLoption;
typedef int CURLcode;
/* import constants */
%constant int CURL_GLOBAL_ALL = CURL_GLOBAL_ALL;
%constant int CURLOPT_URL = CURLOPT_URL;
/* import functions */
int curl_global_init(long flags);
void curl_global_cleanup();
CURL* curl_easy_init();
void curl_easy_cleanup(CURL* curl);
CURLcode curl_easy_setopt(CURL* curl, CURLoption opt, int v);
CURLcode curl_easy_setopt(CURL* curl, CURLoption opt, const char* v);
CURLcode curl_easy_perform(CURL* curl);
ruby的extconf.rb文件
require 'mkmf'
%w{stdc++ curl}.each do|lib|
$libs = append_library $libs, lib
end
create_makefile 'curl'
编译build.sh:
#通过curl.i生成封装后的cpp源码
swig -c++ -ruby curl.i &&
#通过extconf.rb生成Makefile
ruby extconf.rb &&
#通过Makefile生成目标扩展
make
测式文件ruby_test.rb
#!/usr/bin/env ruby
require 'curl'
include Curl
url = ARGV[0] || 'http://www.google.com'
p curl_global_init(CURL_GLOBAL_ALL)
p curl = curl_easy_init()
p curl_easy_setopt(curl, CURLOPT_URL, url)
p curl_easy_perform(curl)
p curl_easy_cleanup(curl)
p curl_global_cleanup()
本文相关的完整源码可在github下载: http://github.com/JiangMiao/ruby_swig_curl_demo
git clone git://github.com/JiangMiao/ruby_swig_curl_demo.git
相关链接:
libcurl
SWIG
一、异常
| 名称 |
描述 |
相当于 |
| $! |
捕获的异常 |
Exception |
| $@ |
异常的backtrace |
Exception#backtrace |
例:
begin
raise "err msg"
rescue
p $! # #<RuntimeError: err msg>
p $@ #["(irb):2:in `irb_binding'", "/usr/local/lib/ruby/1.8/irb/workspace.rb:52:in `irb_binding'", ":0"]
end
二、正则
对于 m=str.match(pattern)
| 变量 |
性质 |
描述 |
相当于 |
| $& |
只读,本地 |
匹配的项 |
m[0] |
| $` |
只读,本地 |
匹配的字符串之前未匹配的部分 |
m.pre_match |
| $\’ |
只读,本地 |
匹配的字符串之后未匹配的部分 |
m.post_match |
| $+ |
只读,本地 |
最后一个匹配的项 |
m[m.size-1] |
| $1,$2 |
只读,本地 |
所指定的匹配的项 |
m[n] |
| $~ |
本地 |
匹配的结果 |
m |
例:
"start-111-222-333-444-end" =~ /(\d+)-(\d+)-(\d+)-(\d+)/
p $& #"111-222-333-444"
p $` # "start-"
p $' # "-end"
p $+ # "444"
p $1 # "111"
p $2 # "222"
p $~[3] # "333"
三、IO/String
| 描述 |
默认 |
说明 |
| $_ |
|
gets,readline最后读入的行 |
| $F |
|
$_.split 仅当选项-a为真时 |
| $/ |
“\n” |
用于gets,readline等分割符 |
| $\ |
nil |
print与IO.write的分割符 |
| $, |
nil |
Array#join的分割符 |
| $; |
nil |
String#split的分割符 |
| $. |
|
ARGF.lineno |
| $< |
|
ARGF |
| $* |
|
ARGV |
| $> |
|
$defout |
| $defout |
|
print与printf的输出变量,缺省为$stdio |
| $stdin |
|
当前标准输入 缺省 STDIN |
| $stdout |
|
当前标准输出 缺省 STDOUT |
| $stderr |
|
当前标准错误输出 缺省 STDERR |
四、进程
| 名称 |
描述 |
| $0 |
当前ruby程序名 |
| $$ |
Process.pid |
| $? |
最后执行的外部程序的返回状态 |
四、其它
| 名称 |
描述 |
| $: |
$LOAD_PATH |
| $” |
已require的module,用于避免二次载入 |
| $DEBUG |
是否为DEBUG状态, -d –debug开启则为真 |
| $FILENAME |
$<.filename |
| $SAFE |
安全等级 |
| $VERBOSE |
verbose选项是开启则为真 |
| $-O |
$/ |
| $-a |
-a选项开启则为真 |
| $-d |
$DEBUG |
| $-F |
$; |
| $-I |
$: |
| $-l |
-lis选项开启则为真 |
| $-p |
-pis选项开启则为真 |
目标:通过本文章学习并编写一个gem ‘hello’
一、认识RubyGems
1、什么是RubyGems
RubyGems是ruby下的包管理系统。最著名gem的当属Rails
2、gem的基本文件布局
| 文件名 |
类别 |
描述 |
| gemspec |
文件 |
gem的规范说明。 |
| lib |
文件夹 |
用于lib文件的存放 |
| bin |
文件夹 |
可执行文件 |
| ext |
文件夹 |
c/c++源文件 |
| tests |
文件夹 |
单元测试文件 |
3、gemspec文件规范常用项
| 名称 |
类别 |
缺省 |
描述 |
| *name |
String |
|
gem名称 |
| *version |
String |
|
版本号 |
| *date |
Time |
Time.now |
Gem创建日期 |
| *platform |
String |
Gem::Platform::Ruby |
gems所使用的平台 |
| *summary |
String |
|
gem描述 |
| *require_paths |
Array |
["lib"] |
用于require调用时的默认路径 |
| files |
Array |
|
gems所包含的文件 |
以上为关键的几个选项,其中打*号的为必须的项,若要添加作者,可执行文件等选项可参见Gem规范
3、编译
gem build gemspec文件
4、安装
gem install 生成的gem
二、编写最简gem hello
1、创建文件与文件夹
hello/hello.gemspec
hello/lib/hello.rb
2、编写 hello.gemspec
Gem::Specification.new do |s|
s.name = 'hello'
s.version = '0.1.0'
s.summary = 'hello gems'
s.files = ["lib/hello.rb"]
end
3、编写 lib/hello.rb
def hello
"HELLO"
end
4、编译
gem build hello.gemspec
5、安装
gem install hello
6、测试
require 'rubygems'
require 'hello'
puts hello
—-
输出HELLO 测试成功
三、相关链接
1、RubyGems官方网站
2、Rubyforge
2、Gem规范
3、本文的hello gem源码
运行命令:
SELECT ns.nspname || '.' || proname || '(' || oidvectortypes(proargtypes) || ')'
FROM pg_proc INNER JOIN pg_namespace AS ns ON (pg_proc.pronamespace = ns.oid)
WHERE ns.nspname = 'public' ORDER BY proname;
可以得到所有函数列表
再依次执行DROP FUNCTION 即可。
Btk 基于 Ruby GTK2 的扩展,大大方便ruby下的gui。
安装:gem install btk
主页:http://btk.rubyforge.org/
Hello World:
require 'rubygems'
require 'btk'
# w will call border_width= or set_border_width with parameter 10
Btk.Window :border_width=>10 do|w|
#alias of signal_connect('delete_event')
w.sig_delete_event do
puts "delete event occurred"
false
end
#alias of signal_connect('destroy')
w.sig_destroy do
puts "destroy event occurred"
Gtk.main_quit
end
# Button will add to w automatically
w.Button "Hello World" do|btn|
btn.sig_clicked do
puts "Hello World"
end
end
w.show_all
end
Gtk.main
MySQL的2个常用函数unix_timestamp()与from_unixtime PostgreSQL并不提供,但通过PostgreSQL强大的扩展性可以轻松的解决问题。
话说远在天边,尽在眼前,文档看仔细,问题迎仞解。PostgreSQL 题供extract与date_part取epoch即可
即
unix_timestamp() = round(date_part(‘epoch’,now()))
from_unixtime(int) = to_timestamp(int)
添加函数unix_timestamp()
CREATE FUNCTION unix_timestamp() RETURNS integer AS $$
SELECT (date_part(‘epoch’,now()))::integer;
$$ LANGUAGE SQL IMMUTABLE;
添加函数from_unixtime()
CREATE FUNCTION from_unixtime(int) RETURNS timestamp AS $$
SELECT to_timestamp($1)::timestamp;
$$ LANGUAGE SQL IMMUTABLE;
如数据库test拥有字段
banned boolean
使用命令
insert into test(banned) values (0)
返回为
ERROR: column “banned” is of type boolean but expression is of type integer
LINE 1: insert into test(banned) values(0)
很是不方便。用cast也没用
难到只能用规定的 TRUE,’t',’true’,'y’,'yes’,’1′吗?
但奇怪的是select 0::boolean支能显示false
使用 like 进行查询 如 explain select* from titles where title like ‘h%’ 一直显示 Seq Scan。 google+百度后,得知要设定locale为C才能使用like。
使用命令 initdb –local=C -D 集群路径 建立新的集群
目标:
当表alphas插入新行时,更新titles的alpha_at为NOW()
当表alphas删除行时,更新titles的alpha_at为NULL
1、安装plpgsql语言到数据库
createlang plpgsql DATABASE
2、建立一个返回为trigger的过程
CREATE OR REPLACE FUNCTION after_alphas_id() RETURNS trigger AS $BODY$
BEGIN
IF( TG_OP='DELETE' ) THEN
UPDATE titles SET alpha_at=null WHERE id=OLD.title_id;
ELSE
UPDATE titles SET alpha_at=NOW() WHERE id=NEW.title_id;
END IF;
RETURN NULL;
END;
$BODY$
LANGUAGE 'plpgsql';
3、创建触发器
CREATE TRIGGER after_alphas_id
AFTER INSERT OR DELETE
ON alphas
FOR EACH ROW
EXECUTE PROCEDURE after_alphas_id();
从rails回来,重新用起了php,起因还是由于rails render一个63k的view要多花去10ms,这个view就一个erb fragment缓存,,即由原来每个响应20ms下降到30ms,降低了足足50%,很受伤,后然尝试使用merb,但merb不太习惯,正值ruby1.9.1,Rails2.3发页,又尝试ruby1.9.1,可惜很多gems都未能完善,fcgi,mongrel都无法工作,只能用回了1.8.7。最后无奈之下用回了php。用php重写了所有代码后,一模一样的操作那个63k的页面只需10ms。
但rails给我的启发是巨大的,现在我的目录结构也仿rails, 如app,config,public,log,tmp等。我甚至写了个Rakefile用来管理文件的常用操作,使用了ruby的2个月。学到了不少。ruby我还会继续用他,作为我的刀,希望ruby越来越好,早一天让我从php又回到了ruby。
近期评论