存档

‘3 ruby/c++’ 分类的存档

Ruby下使用SWIG封装libcurl

2010年9月2日 没有评论

本文通过在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

分类: 3 ruby/c++ 标签:

rb_yield让ruby/c++更加紧密

2009年1月26日 没有评论

用c++写ruby模块提升性能效果显著一文让我初尝甜头,但未免连render都用c++也太得不尝失。自从使用了rb_yield,一切问题迎刃而解。

如代码

class Test
  def foo
    yield
  end
end

相对应的c++代码则为

#include "ruby.h"
typedef VALUE(*RUBY_FUNC)(...);
extern "C" VALUE t_foo(VALUE self)
{
  //do something by c++
  rb_yield();
  //do something by c++
}
VALUE cTest = rb_define_class("Test",rb_cObject);
rb_define_method(cTest,"foo",(RUBY_FUNC)t_foo,1);

非常的方便有效。

分类: 3 ruby/c++, 编程 标签:

用c++写ruby模块提升性能效果显著

2009年1月17日 1 条评论
对于生成600项item的树型目录。
纯ruby代码大约200ms
包括rails初始化(0-6ms),mysql查询(0-2ms),树型生成(20-30ms),递归render,其它。

经过c++重写后,全部只需10ms。实在太爽啦。
如果那递归render都用c++代替,那感觉是用C++写网页,而不是用ruby写网页,利用不到rails提供的很多特性。但递归render 600项实在耗时,鱼和熊掌不能兼得,得另想法子。

分类: 3 ruby/c++, ruby, 编程 标签:

使用SWIG扩展ruby性能

2009年1月16日 没有评论
  在使用ruby/rails的过程中,确实发现有时性能不尽人意,如生成一个拥有600项的item的3层树形结构目录要花去20ms,为提高性能在学习用c/c++写ruby模块的过程中,认识了swig,rubyInline等一系列帮助编写c/c++来提升ruby性能的辅助工具。
  rubyInline用于内嵌c/c++程序,简单快捷,
  swig则帮助我们更容易地用c/c++写出独立的ruby模块。 

swig的入门使用方法
目标:用swig/c++编写一个ruby模块Test,并提供add方法作加法运算。
相关文件:

  • test.i 接口
  • test.h 头文件
  • test.cxx 函数实现
  • extconf.rb 用于生成makefile
  • (自动)test_wrap.cxx swig生成的test封装
  • (自动)Makefile Makefile文件由ruby extconf.rb得到
  • (自动)test.so ruby模块 由make得到

1、建立接口文件test.i

%module test
%{
//包含头文件
#include "test.h"
%}
//接口add
int add(int,int);

2、编写wrap文件

swig -c++ -ruby test.i

得到test封装文件 test_wrap.cxx

3、编写test.h与test.cxx

//test.h
#ifndef _TEST_TEST_H
#define _TEST_TEST_H
extern int add(int,int);
#endif
//test.cxx
#include "test.h"
int add(int left,int right)
{
        return left+right;
}

4、编写extconf.rb用于快速生成makefile

require 'mkmf'

dir_config 'test'
#stdc++库,add函数未用到
$libs = append_library $libs,'stdc++'
create_makefile 'test'

运行 ruby extconf.rb 得到 Makefile 文件

5、生成test模块
运行 make 得到模块 test.so

6、测试

irb
irb(main):001:0> require 'test'
=> true
irb(main):002:0> Test.add 3,4
=> 7
irb(main):003:0> Test.add 3333333333333333333333,44444444444444444
TypeError: Expected argument 0 of type int, but got Bignum 3333333333333333333333
        in SWIG method 'add'
        from (irb):3:in `add'
        from (irb):3
        from :0
irb(main):004:0>

测试成功

7、swig
swig支持很多c++的高级特性来编写ruby的模块,如类,继承,重载,模板,stl等。

8、相关链接

9、备注
本文的add函数过于简单,对比ruby 3+4性能不升反降。

分类: 3 ruby/c++, 编程 标签: