分享

Ruby使用C/C 扩展(包括windows和linux) | Only For Sun...

 左目右于 2012-03-28

Ruby使用C/C++扩展,可以让ruby变得很强大。
本文根据http://raylinn./blog/629329学习而来。
先说说流程,ruby C/C++扩展,先由mkmf生成Makefile,之后再用make(linux),nmake(windows vc++)生成动态链接库。
放到ruby对应目录后,直接require即可。
步骤:
1.编写C++文件(建议C/C++都用.cpp吧)
HelloTest.cpp

#include<stdio.h>   
#include<ruby.h>   
 
class TestClass  
{  
public:  
    TestClass(void){};  
    ~TestClass(void){};  
 
    void SayHello(char* msg)  
    {  
               printf("Ruby C/C++ extention Example cdlz.\n");  
               printf("Your Name is: %s\n",msg);  
    }  
};  
 
//VALUE self这个是不变的。指向自己。 第二个: VALUE name则是我们这个函数需要的参数。   
VALUE method_sayhello(VALUE self,VALUE name){  
    long length=0;  
    char* yourname = rb_str2cstr(name, &amp;length);  //rb_str2cstr,转换到C语言的字符串
    TestClass* test=new TestClass();  
    test-&gt;SayHello(yourname);  
    delete test;  
	return rb_str_new2(yourname); //rb_str_new2,由C语言的字符串转换为Ruby的String。
};  
 
VALUE method_cfunction(VALUE self, VALUE va, VALUE vb)
{
	int a = NUM2INT(va);
	int b = NUM2INT(vb);
 
	return INT2NUM(a+b);
}
 
VALUE hellotest = Qnil; //Qnil 即为 NULL 
/*
如果全部都是C的,则需要加上extern "C" void Init_HelloTest()
*/
void Init_HelloTest(){  
  hellotest = rb_define_module("HelloTest");  
  //定义一个ruby方法,在ruby中调用。最后一个参数为 ruby方法的参数个数 
  rb_define_method(hellotest, "sayhello", RUBY_METHOD_FUNC(method_sayhello), 1);  
  rb_define_method(hellotest, "cfunction_plus", RUBY_METHOD_FUNC(method_cfunction), 2);   
};

上述代码,实现了两个ruby方法:sayhello和cfunction_plus
像返回值,参数值必须要注意类型,C和ruby之间的转换,可以参见Programming Ruby一书第280页。同时也有说到其他的方法。

2. extconf.rb

require 'mkmf'  
 
extension_name = "HelloTest" 
dirbase="D:/ruby/vc"
ruby_lib_base= dirbase+"/lib"
ruby_include_base= dirbase+"/include"
 
dir_config(extension_name)  
#如果是windows则取消下面注释,注意,目录名称不能有空格
#dir_config(extension_name,ruby_include_base,ruby_lib_base)
 
create_makefile(extension_name)

之后运行 ruby extconf.rb,以便生成Makefile文件。

linux下,一般直接运行make即可生成so,然后make install 即可。
windows下,必须装有visual studio,然后使用nmake即可。
visual studio要注意版本问题,直接去掉ruby的头文件判断吧:
ruby安装目录下: D:\ruby\ruby186\lib\ruby\1.8\i386-mswin32
config.h第二行注释掉即可:
#if _MSC_VER != 1200
//#error MSC version unmatch
#endif
然后使用nmake编译。
关于VC++ 7.0以上版本有一些特殊情况,就是manifest文件,这是发布一个.exe的可执行文件或者一个.dll的动态库所需要的,默认情况下,.manifest文件需要内嵌到你的类库中去。可使用下述批处理脚本:

ruby extconf.rb  
nmake  clean
nmake  
mt -manifest %1.so.manifest -outputresource:%1.so;2  
nmake install

如果没有错误,编译通过,windows下可以使用如下命令查看dll导出函数情况:
dumpbin -exports HelloTest.so
。。。
1 0 00001120 Init_HelloTest = ?Init_HelloTest@@YAXXZ (void __cdecl Init_HelloTest(void))
。。。
linux下: nm -g HelloTest.so
最后附上ruby测试脚本:

require "HelloTest"
 
include HelloTest  
 
puts HelloTest.sayhello("aaa")
puts HelloTest.cfunction_plus(111,222)
 
puts HelloTest.methods - Object.methods

注意:如果是在扩展中有输出,则只有在ruby的输出全部打印完毕后,才会有扩展中的输出(直接使用ruby test.rb,顺序有正常。。。暂时无解。。。)。
本例的打印结果:

aaa
333
Ruby C/C++ extention Example cdlz.
Your Name is: aaa

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多