- 浏览: 221373 次
文章分类
- 全部博客 (155)
- activerdf (1)
- html (0)
- depoly (1)
- src_present (1)
- ria (1)
- beast (2)
- cache (1)
- acts_as_atggable (1)
- http (1)
- talk (1)
- rest (1)
- rake (1)
- vim (2)
- active_resource (1)
- jruby activerecord_jdbc (1)
- nginx (1)
- plugin (1)
- gui (1)
- push (1)
- 介紹 (1)
- rails (19)
- regex (1)
- svn (1)
- 說明 (13)
- gem (4)
- ruby (16)
- rails12 (2)
- fastcgi (1)
- os (1)
- mongrel (5)
- scale (4)
- quickref (1)
- 安裝 (5)
- tiobe_index (2)
- planet (1)
- lighttpd (4)
- Capistrano (1)
- 嘴砲 (2)
- performance (4)
- ide (6)
- jruby (12)
- railsconf (1)
- activerecord (2)
- ajax (3)
- ruby.net (1)
- 程式 (1)
- actionmailer (1)
- company (2)
- security (1)
- redmine (1)
- book (2)
- news (2)
- 廣告 (1)
最新评论
-
bluerose:
你好,我下载了文件是Textile格式的。应该怎么阅读呢?我想 ...
Textile,RedCloth,Vim -
whg333:
谢谢,LZ是香港或台湾人士?怎么都是繁体?
學習 Ruby on Rails 要看的書 -
jerry:
https可以作吗?
Net::HTTP 使用方式 -
thinhair:
能不能具体点? 这个Config文件在那啊?
用 JRuby 來連接 Oracle -
dearsuper:
就是希望少占资源。
Another Ruby IDE:InterlliJ Idea for Ruby Plugin launch
以下文章最早發表於 2006.08.06, ptt Ruby 板。由於這裡的版面跟 BBS 有極大的差異,所以稍微調整了一下排版。不過程式碼的部份可能很難調整到方便閱讀,這點也就請見諒了。
http://www.swig.org/
SWIG is an interface compiler that connects programs written in C and C++ with scripting languages such as Perl, Python, Ruby, and Tcl.
也就是,讓 C/C++ 與 scripting language 溝通的介面產生器。目前支援 13 種程式語言(含非 scripting language):
* Allegro Common Lisp
* C#
* Chicken
* Guile
* Java
* Modula-3
* Mzscheme
* OCAML
* Perl
* PHP
* Python
* Ruby
* Tcl
之前我測了一些 Ruby 與 C++ 的溝通方式,以下將簡單介紹一下測試的方法。首先先看到使用方式,我想這個應該是最重要的部份,畢竟如果使用不便,那其他的也不用再多說什麼了…。
以下這個程式是一個簡單的 type wrapper,(傳值版)由 template parameter 指定型別,data() 當 getter, data(type) 當 setter. 另外在 c'tor 和 d'tor 中插入 IO 來追蹤物件的生成與摧毀:
有了這個 .h 檔的介面後(這裡同時也包含實作),接下來我們需要的是一個由 swig 產生的膠水,將 C++ 介面與 Ruby 介面混合,暫時命名為:Wrapper.i, 詳細做法等一下我們再來看。總之最終我們將產生一個動態連結檔,也就是一個 Ruby 的 module, 叫 Wrapper. 不過需要一提的是,由於 Ruby 本身不支援 template, 所以我們在 Wrapper.i 中必須明確指出我們需要什麼型別,否則 Ruby 會無法使用。(更明確來講,純 template 根本無法 compile)
所以在 Wrapper.i 中,裡面有一行是這個:
%template(Integer) Wrapper<int>;
這句話的意思是,將 Wrapper<int> 這個型別取作 Integer. 於是 Ruby module 做好後,可以使用 Integer 這個型別。
雖然我中間還有很多測試,不過直接看目前的最後結果吧。寫一個 Ruby 程式,內容如下:
ok, 可是原本插入 C++ 的 c'tor 中的 IO 呢?整個程式的輸出結果是這樣:
C++: Wrapper is created, which is '123' .
130
460
C++: Wrapper is decayed, which is '460' .
也就是說,C++ 的 c'tor 與 d'tor 有被確實喚起。這樣說不定可以替 Ruby 實作出 d'tor...不過這是題外話。
另外,剛剛程式中的 fat.data 與 fat.data(456) 確實是喚起正確的 getter 與 setter, 可是 Ruby 沒有 overload? 我沒有實際去看,但我猜他內部大概是這樣實作的:
所以如果你想要重新定義其中一個 overloaded method, 做不到…可能必須找到他實際的名字才有辦法。
那麼我們再來看到由 C++ 呼喚 Ruby... 否則不就太寂寞了嗎?基本上 Ruby 本身就提供了良好與 C 溝通的機制,照用不就好了?是這樣說沒錯,可是說真的我很討厭 C 的介面…囧rz
常常會要你記下一堆有的沒的,感覺很討厭。所以我覺得需要一個 C++ 的 wrapper, 一個可以輕鬆呼叫 Ruby 的方式。後來我找到這個:
http://www.sourcepole.com/sources/software/c++ruby/
不過這個東西實在是寫得不好,沒有處理 finalize 的部份。不知道還有沒有其他類似的 wrapper 可以用,所以我就暫時用這個來改。改寫他 singleton 的實作,還有記得在 d'tor 中呼叫 ruby_finalize();
最後的結果是,我可以這樣寫:
那個 test.rb, 就是上面寫好拿來測試 Ruby 呼叫 C++ 的程式。於是整個輸出結果就是:
C++: Wrapper is created, which is '123' .
123
456
C++: Wrapper is created, which is '123' .
130
460
C++: Wrapper is decayed, which is '460' .
C++: Wrapper is decayed, which is '456' .
第一行是從 C++ 建構的 Integer; 123, 456 則是 cout 輸出的。第四行的 123 則是 test.rb 產生 class Test < Wrapper::Integer 那個。130, 460 則是 Ruby 的 puts 產生出來的。
最後兩個 decayed 則是 Ruby 的 gc 正確在程式結束時摧毀物件輸出的順序剛好跟 c'tor 反過來,一切正常。
最後就來看怎麼實現這個的。Wrapper.i 是這樣寫的:
%module Wrapper
%{
#include "Wrapper.h"
%}
%include "Wrapper.h"
%template(Integer) Wrapper<int>;
這些語法請參考 SWIG 的網站,那邊都有詳細說明。甚至是 C++ 的多重繼承,在 Ruby 中也能使用。當然多少可能會有點限制,但似乎可以實現一定的功能。
下指令:
swig -c++ -ruby Wrapper.i
這樣就可以以 Wrapper.i 這個介面檔實作出由 Ruby 溝通 C++ 的程式。那個程式會叫做 Wrapper_wrap.cxx, 也就是 YOUR_NAME_wrap.cxx
再來就是將所有的程式打包成一個動態連結檔了,所有的檔案是:Wrapper.h (包含實作), Wrapper_wrap.cxx (SWIG 的膠水)。方便的做法是使用 Ruby 的 lib, 叫 mkmf
寫一個 Ruby 程式叫 mkmf.rb, 內容是:
require 'mkmf'
$libs = append_library($libs, "stdc++")
create_makefile(ARGV[0])
這邊是由於我個人方便,所以這樣寫的。第一行含入 mkmf, 第二行是因為我用到 C++ 標準函數庫(cout),所以必須連結 stdc++ 才行(我的系統是 GCC, VC++ 的話我不清楚)接著由 create_makefile 產生出我要的 makefile, 名稱由 cmd line 輸入。這邊我是輸入 Wrapper.(btw, 有人知道 stdc++ 可否動態連結嗎?)
接著就可以由 make 將 Wrapper.h 和 Wrapper_wrap.cxx 合併做出 Wrapper.so(我想 VC++ 系統應該會做出 Wrapper.dll 之類的)
最後要提的是,整個程式的執行環境。由於我是在 cygwin 下作業的,所以獨立執行這些程式需要的是:
cygwin1.dll 1.78 MB
cygruby18.dll 703 KB
cygcrypt-0.dll 6.5 KB
我想如果在 windows 下由 VC++ compile 的話,應該就只會需要 Ruby interpreter 的 dll 檔(這裡是 cygruby18.dll)。不過我就沒有做這一步的測試了,留給讀者當作練習吧 XD
(忽然心血來潮所以整理了這些東西)
2006.08.06 godfat 真常
延伸閱讀
http://www.swig.org/
SWIG is an interface compiler that connects programs written in C and C++ with scripting languages such as Perl, Python, Ruby, and Tcl.
也就是,讓 C/C++ 與 scripting language 溝通的介面產生器。目前支援 13 種程式語言(含非 scripting language):
* Allegro Common Lisp
* C#
* Chicken
* Guile
* Java
* Modula-3
* Mzscheme
* OCAML
* Perl
* PHP
* Python
* Ruby
* Tcl
之前我測了一些 Ruby 與 C++ 的溝通方式,以下將簡單介紹一下測試的方法。首先先看到使用方式,我想這個應該是最重要的部份,畢竟如果使用不便,那其他的也不用再多說什麼了…。
以下這個程式是一個簡單的 type wrapper,(傳值版)由 template parameter 指定型別,data() 當 getter, data(type) 當 setter. 另外在 c'tor 和 d'tor 中插入 IO 來追蹤物件的生成與摧毀:
// in Wrapper.h
#include <iostream>
template <class Data>
class Wrapper{
public:
Wrapper(Data new_data): data_(new_data){
std::cout << "C++: Wrapper is created, which is '"
<< data_ << "' .\n";
}
~Wrapper(){
std::cout << "C++: Wrapper is decayed, which is '"
<< data_ << "' .\n";
}
Data data() const{ return data_; }
void data(Data new_data){ data_ = new_data; }
private:
Data data_;
};
有了這個 .h 檔的介面後(這裡同時也包含實作),接下來我們需要的是一個由 swig 產生的膠水,將 C++ 介面與 Ruby 介面混合,暫時命名為:Wrapper.i, 詳細做法等一下我們再來看。總之最終我們將產生一個動態連結檔,也就是一個 Ruby 的 module, 叫 Wrapper. 不過需要一提的是,由於 Ruby 本身不支援 template, 所以我們在 Wrapper.i 中必須明確指出我們需要什麼型別,否則 Ruby 會無法使用。(更明確來講,純 template 根本無法 compile)
所以在 Wrapper.i 中,裡面有一行是這個:
%template(Integer) Wrapper<int>;
這句話的意思是,將 Wrapper<int> 這個型別取作 Integer. 於是 Ruby module 做好後,可以使用 Integer 這個型別。
雖然我中間還有很多測試,不過直接看目前的最後結果吧。寫一個 Ruby 程式,內容如下:
#!/usr/bin/ruby
# in test.rb
require 'Wrapper' # 讀入剛剛做好的 Wrapper module
class Test < Wrapper::Integer # 繼承 C++ 寫好的 Wrapper<int>
def initialize(new_data) # c'tor 其實可以省略,因為可以使用
super(new_data) # C++ 中寫好的 Wrapper
ok, 可是原本插入 C++ 的 c'tor 中的 IO 呢?整個程式的輸出結果是這樣:
C++: Wrapper is created, which is '123' .
130
460
C++: Wrapper is decayed, which is '460' .
也就是說,C++ 的 c'tor 與 d'tor 有被確實喚起。這樣說不定可以替 Ruby 實作出 d'tor...不過這是題外話。
另外,剛剛程式中的 fat.data 與 fat.data(456) 確實是喚起正確的 getter 與 setter, 可是 Ruby 沒有 overload? 我沒有實際去看,但我猜他內部大概是這樣實作的:
def data(*args)
case args.size
when 0 then return self.data_a
when 1 then return self.data_b(args[0])
end
end
所以如果你想要重新定義其中一個 overloaded method, 做不到…可能必須找到他實際的名字才有辦法。
那麼我們再來看到由 C++ 呼喚 Ruby... 否則不就太寂寞了嗎?基本上 Ruby 本身就提供了良好與 C 溝通的機制,照用不就好了?是這樣說沒錯,可是說真的我很討厭 C 的介面…囧rz
常常會要你記下一堆有的沒的,感覺很討厭。所以我覺得需要一個 C++ 的 wrapper, 一個可以輕鬆呼叫 Ruby 的方式。後來我找到這個:
http://www.sourcepole.com/sources/software/c++ruby/
不過這個東西實在是寫得不好,沒有處理 finalize 的部份。不知道還有沒有其他類似的 wrapper 可以用,所以我就暫時用這個來改。改寫他 singleton 的實作,還有記得在 d'tor 中呼叫 ruby_finalize();
最後的結果是,我可以這樣寫:
#include "rubyeval.h" // 就是上面抓來的那個
#include <ruby.h> // embedded ruby 必要的東西,去 ruby-lang 就可以抓
int main(){
RubyEval& ruby = RubyEval::instance();
ruby.eval("require 'Wrapper'"); // 直接用字串執行 Ruby
// 這邊是含入剛剛做好的 C++ => Ruby mod
// 當然這東西要先 compile 好
ruby.eval("fat = Wrapper::Integer.new(123)"); // 直接建立物件
std::cout << NUM2INT(ruby.eval("fat.data")) << std::endl; // 輸出 123
ruby.eval("fat.data(456);"); // 設值 456
std::cout << NUM2INT(ruby.eval("fat.data")) << std::endl; // 輸出 456
ruby.run_file("test.rb"); // 直接執行 ruby 程式
}
那個 test.rb, 就是上面寫好拿來測試 Ruby 呼叫 C++ 的程式。於是整個輸出結果就是:
C++: Wrapper is created, which is '123' .
123
456
C++: Wrapper is created, which is '123' .
130
460
C++: Wrapper is decayed, which is '460' .
C++: Wrapper is decayed, which is '456' .
第一行是從 C++ 建構的 Integer; 123, 456 則是 cout 輸出的。第四行的 123 則是 test.rb 產生 class Test < Wrapper::Integer 那個。130, 460 則是 Ruby 的 puts 產生出來的。
最後兩個 decayed 則是 Ruby 的 gc 正確在程式結束時摧毀物件輸出的順序剛好跟 c'tor 反過來,一切正常。
最後就來看怎麼實現這個的。Wrapper.i 是這樣寫的:
%module Wrapper
%{
#include "Wrapper.h"
%}
%include "Wrapper.h"
%template(Integer) Wrapper<int>;
這些語法請參考 SWIG 的網站,那邊都有詳細說明。甚至是 C++ 的多重繼承,在 Ruby 中也能使用。當然多少可能會有點限制,但似乎可以實現一定的功能。
下指令:
swig -c++ -ruby Wrapper.i
這樣就可以以 Wrapper.i 這個介面檔實作出由 Ruby 溝通 C++ 的程式。那個程式會叫做 Wrapper_wrap.cxx, 也就是 YOUR_NAME_wrap.cxx
再來就是將所有的程式打包成一個動態連結檔了,所有的檔案是:Wrapper.h (包含實作), Wrapper_wrap.cxx (SWIG 的膠水)。方便的做法是使用 Ruby 的 lib, 叫 mkmf
寫一個 Ruby 程式叫 mkmf.rb, 內容是:
require 'mkmf'
$libs = append_library($libs, "stdc++")
create_makefile(ARGV[0])
這邊是由於我個人方便,所以這樣寫的。第一行含入 mkmf, 第二行是因為我用到 C++ 標準函數庫(cout),所以必須連結 stdc++ 才行(我的系統是 GCC, VC++ 的話我不清楚)接著由 create_makefile 產生出我要的 makefile, 名稱由 cmd line 輸入。這邊我是輸入 Wrapper.(btw, 有人知道 stdc++ 可否動態連結嗎?)
接著就可以由 make 將 Wrapper.h 和 Wrapper_wrap.cxx 合併做出 Wrapper.so(我想 VC++ 系統應該會做出 Wrapper.dll 之類的)
最後要提的是,整個程式的執行環境。由於我是在 cygwin 下作業的,所以獨立執行這些程式需要的是:
cygwin1.dll 1.78 MB
cygruby18.dll 703 KB
cygcrypt-0.dll 6.5 KB
我想如果在 windows 下由 VC++ compile 的話,應該就只會需要 Ruby interpreter 的 dll 檔(這裡是 cygruby18.dll)。不過我就沒有做這一步的測試了,留給讀者當作練習吧 XD
(忽然心血來潮所以整理了這些東西)
2006.08.06 godfat 真常
延伸閱讀
发表评论
-
ludy 0.0.4 released
2007-08-12 17:00 1160花了一點時間再測試了一下 curry 的實做,i am gla ... -
ludy 0.0.3 released
2007-08-07 06:09 1279睽違已久,忽然心血來 ... -
[心得] RubyCocoa
2007-07-25 14:37 1462轉自 ptt MacDev 板作者 godfat (godfa ... -
ruby facets
2007-07-08 14:22 1134老實講,ruby 有一個地方真討厭,那就是每次都把我想做的東西 ... -
心愛的 Object 變心啦
2007-05-15 15:36 887剛剛發現一個很有趣的事情,寫 code 的時候,有兩個 Mod ... -
[Ruby] recursive lambda
2007-04-16 15:36 1084[Ruby] recursive lambda==本文 ... -
Struct:簡單的宣告物件方式
2007-04-04 03:08 1275在 PHP 裡面,很多時候我們會用到 Hash 來傳遞變數,像 ... -
class 與 instance
2007-03-27 12:28 1162不知道為何,最近不管是私事或公事似乎都很多。造成的結果就是很多 ... -
Gentoo 上面跑 DRB 可能出現的問題
2007-03-21 13:35 1174有時候在 Gentoo 上面使用一些有關 DRB 的東西,像是 ... -
why scripting?
2007-03-16 15:00 1094why scripting?簡單一句話就是:「為了增進生產力」 ... -
為啥我得升級 Ruby 1.8.6
2007-03-16 16:11 1202為什麼我得升級 Ruby 1.8.6?會跟 Rails 衝突, ... -
Ruby 1.8.6 Release:要升級請三思
2007-03-13 14:29 1092今天早上宣布的,想看詳細情形,或是下載 Source 請看這裡 ... -
M$ 也加入 Ruby 這個大戰場了嗎?
2007-02-25 09:04 1190InfoWorld 上面有消息指出,M$ 對 Ruby 這個程 ... -
Ruby on PSP?
2007-02-03 04:06 1187DSCN0841Originally uploaded ... -
[轉錄] 世界喜愛 Ruby 的理由 - 專訪松本行弘(摘要)
2007-01-06 03:26 1342這是日経 BP主辦的「次世代開發論壇」時的訪談 Matz (R ...
相关推荐
在使用ruby/rails的过程中,确实发现有时性能不尽人意,如生成一个拥有600项的item的3层树形结构目录要花去20ms,为提高性能在学习用c/c++写ruby模块的过程中,认识了swig,rubyInline等一系列帮助编写c/c++来提升...
SWIG(Simplified Wrapper and Interface Generator)是一种开源的软件开发工具,旨在帮助程序员将C或C++代码库与高级编程语言如Python、Perl、Ruby、Tcl、PHP等进行接口封装,实现代码重用和扩展。使用SWIG,可以...
SWIG(Simplified Wrapper and Interface Generator)是一种开源的接口生成工具,可以将C/C++语言与各种脚本语言集成,包括Python、Tcl、Perl、 Ruby等。SWIG的主要功能是生成一个 wrapper(封装器),将C/C++代码...
C 和 C++ 被公认为...SWIG 允许您向广泛的脚本语言公开 C/C++ 代码,包括 Ruby、Perl、Tcl 和 Python。本文使用 Ruby 作为公开 C/C++ 功能的首选脚本接口。要理解本文,您必须具备 C/C++ 与 Ruby 方面的相应知识。
SWIG能应用于各种不同类型的语言包括常用脚本编译语言例如Perl, PHP, Python, Tcl, Ruby and PHP。支持语言列表中也包括非脚本编译语言,例如C#, Common Lisp (CLISP, Allegro CL, CFFI, UFFI), Java, Modula-3, ...
SWIG(Simplified Wrapper and Interface Generator)是一款强大的工具,用于将C和C++代码自动绑定到多种脚本语言,如Python、Perl、Ruby等。它简化了创建这些语言的接口的过程,使得C/C++库可以方便地在各种脚本...
In a nutshell, SWIG is a compiler that takes C/C++ declarations and creates the wrappers needed to access those declarations from other languages including including Perl, Python, Tcl, Ruby, Guile, ...
它使得C或C++的程序可以方便地与多种高级语言,如Python、Java、Perl、Tcl、Ruby等进行交互。SWIG通过解析C或C++的头文件,生成相应的接口代码,从而让这些语言能够调用原生的C/C++函数和对象。 SWIG的核心功能在于...
- **3.2.1.7 Ruby** **3.3 SWIG 在 Cygwin 和 MinGW 上的使用** - **3.3.1 构建 swig.exe** SWIG 可以在 Cygwin 和 MinGW 环境下构建: - 使用 MinGW 和 MSYS - 使用 Cygwin - 替代方案 - **3.3.2 在 ...
SWIG能够在不需要修改现有代码的基础上,自动创建其他编程语言(如Perl、Python、Tcl、Ruby、Guile和Java)访问C/C++声明所需的包装器(wrappers)。这一特性极大地促进了不同语言开发者的协作与代码复用,提高了...
SWIG不仅支持C++,还支持许多其他语言,如Java、Perl、Ruby等。通过SWIG,开发者可以将现有的C++代码快速地包装成Python模块,无需手动编写复杂的Python-C接口代码。 **CMake与SWIG结合使用** 在CMake项目中整合...
SWIG(Simplified Wrapper and Interface Generator)是一款强大的工具,用于将C和C++代码与多种高级语言(如Python、Perl、Java、Ruby等)连接起来。`swig-2.0.10.tar.gz` 是SWIG的一个版本,具体是2.0.10版的源码...
它通过自动生成必要的封装代码,使C/C++库能够被多种脚本语言调用,如Perl、Python、Ruby等,无需开发者手动编写繁琐的接口代码。 **2.1 SWIG是什么?** SWIG是一种自动化工具,用于构建C/C++库与各种脚本语言之间...
SWIG(Simplified Wrapper and Interface Generator)是一款强大的工具,用于将C和C++代码自动绑定到多种脚本语言,如Python、Perl、Tcl、Java、Ruby等。它简化了创建这些语言的接口过程,使得C/C++库可以方便地在...
2. **语言支持**:SWIG支持多种编程语言,如Python、Ruby、Perl、Tcl、Java、JavaScript、C#、Lua等,使得跨语言开发变得更加便捷。 3. **类型转换**:SWIG能自动处理不同语言之间的类型转换,如C/C++的指针、...
SWIG是一个强大的工具,主要用于创建程序接口,它可以将C和C++代码与多种高级语言如Python、Perl、Java、Ruby、Tcl、PHP、JavaScript等相连接。它的主要用途是简化创建这些脚本语言的绑定,使得C或C++库可以轻松地在...
它使得开发者能够轻松地将C或C++编写的库与多种高级编程语言,如Python、Java、Perl、Ruby等进行集成。SWIG的工作原理是通过解析C或C++头文件,自动生成必要的接口代码,从而让这些低级语言的库能够在高级语言环境中...
SWIG(Simplified Wrapper and Interface Generator)是一款强大的工具,用于将C和C++代码与多种高级语言(如Python、Perl、Java、Ruby等)接口。在这个案例中,我们讨论的是SWIG的2.0.12版本,它是一个用于安装...
7. **多语言支持**:SWIG支持多种脚本语言,如Python、Perl、Ruby、PHP、JavaScript等,使得开发者能够轻松地将C/C++库集成到他们所选择的脚本环境中。 8. **模块和命名空间**:SWIG能够将C/C++的命名空间和模块...
5. **扩展语言支持**:除了常见的Python、Java等,SWIG还支持许多其他语言,如Ruby、PHP、Lua等。这意味着你可以用SWIG将C/C++库轻松地引入到各种不同的软件开发环境中。 6. **文档生成**:SWIG可以与Doxygen等文档...