`

【Ray谈Ruby] 利用MKMF编写Ruby的Windows扩展 之一

阅读更多
MKMF可以帮你自动成Ruby扩展库的Makefile,这样生成的.so或.dll链接库,以直接在ruby程序中被require,鉴于Ruby的Win32API写得极其糟糕,强烈建议在需要与Windows API打交道的时候,直接放弃Ruby的Win32API,而采用MKMF来扩展ruby。

这里,我会着重谈Windows平台,因为Windows平台提供了大量的SDK和详细的文档,可以很快地为Ruby扩展出丰富的功能。

MKMF通常以一个名为extconf.rb的ruby脚本开始,运行该脚本会自动生成编译所需的Makefile. 简单的看一下extconf.rb的内容,十分简单明了
require 'mkmf'
# Give it a name
extension_name = 'bootextract'
# The destination
dir_config(extension_name)
dir_config(extension_name,'C:/work/Include','C:/work/lib')
# Do the work
create_makefile(extension_name)


这里着重说一下
dir_config(extension_name,'C:/work/Include','C:/work/lib')


第二个参数用来添加编译所需include路径,第三个则是library的路径。MKMF编写的makefile,不能接受路径中有空格,建议和例子一样,将所需的SDK的头文件和库文件拷贝到不带空格的路径中。

mkmf的ruby文件就介绍到这里。程序的功能由C或C++来实现,VC++通过文件的扩展名.c或者.cpp来判断它是一个C程序还是C++程序,在Windows平台下编写扩展,强烈建议命名为.cpp而不是.c, 否则会出现许多奇怪的错误.

此外建议程序的功能主体应该采用面向对象的方式编写,而不要写成一堆方法的堆积,如例子所示:

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include "ruby.h"

class Test
{
public:
	Test(void){};
	~Test(void){};

	void Echo(TCHAR* msg)
	{
               _tprintf_s(_T("MKMF Example by Ray Linn"));
               _tprintf_s(_T("Echo Message: %s"),msg);
	}
};

--------------------------------------------------------------------
VALUE method_extract(VALUE self,VALUE target){
    long length=0;
    char* name = rb_str2cstr(target, &length);
    Test* test=new Test();
    test->Echo(name);
    delete test;
    return 0;
};

VALUE BootExtract = Qnil;
void Init_bootextract(){
  BootExtract = rb_define_module("BootExtract");
  rb_define_method(BootExtract, "extract", RUBY_METHOD_FUNC(method_extract), 1); 
};


程序在分割线出分为两大部分,上半部是程序的主体,你可以单独把这个程序置于一个头文件中,这部分是ruby扩展的实际功能实现,下半部分则是提供了功能体和ruby之间如何通讯的说明。

rb_define_method(BootExtract, "extract", RUBY_METHOD_FUNC(method_extract), 1); 


注意在CPP中,必须用 RUBY_METHOD_FUNC来定义函数指针,否则编译会出错,第四个参数之名了方法的参数个数(文中的1 指的就是 VALUE target)。

开始编译

现在大部分开发者都是用Visual Studio 2005以上的版本(包括Express版),而  $RUBY_HOME/lib/ruby/1.8/i386-mswin32/config.h这个文件,对VC的版本做了一些限制(通常是编译ruby的VC版本),所以有时会报告VC版本不对而退出编译。解决这个问题,难点的方法可以用你手上的VC重新编译过ruby(参考另文),简单的办法,就是打开这个config.h,直接把以下三行注释掉:
    #if _MSC_VER != 1200
    #error MSC version unmatch
    #endif


再次运行
> ruby extconf.rb
> nmake

中间有一些warning,纯属于MKMF的狗屁倒灶,可以忽略。

关于VC++ 7.0以上版本有一些特殊情况,就是manifest文件,这是发布一个.exe的可执行文件或者一个.dll的动态库所需要的,默认情况下,.manifest文件需要内嵌到你的类库中去:
mt -manifest mytest.so.manifest -outputresource:mytest.so;2 


现在nmake install的话,Windows的Library就可以顺利在ruby中运行了。
分享到:
评论
2 楼 ray_linn 2010-07-21  
随手写的一个make.bat
ruby extconf.rb
nmake
mt -manifest %1.so.manifest -outputresource:%1.so;2
nmake install



用的时候,后面带上你写在extconf.rb的extname....随便就在VC下搞定MKMF。
1 楼 mathgl 2010-04-14  
感觉上比用python和swig复杂许多...

相关推荐

    RubyCExtensions

    - **简介**:mkmf 是一个用于生成平台特定的 Makefile 文件的工具,它可以帮助开发者轻松地构建 Ruby 的 C 扩展模块。 - **使用方法**: - 创建名为 `extconf.rb` 的文件,并在其中写入以下代码: ```ruby ...

    Ruby使用C++扩展实例(含C++扩展代码示例)

    早年写过用C++ + SWIG写Ruby插件的文,但实际中还是以原生C++写Ruby扩展,因为也相当简单。但长久没用还是会忘记,不得不翻以前的老代码回忆,写下这篇博文,若下次再忘记,也不至于去翻仓库。 建立 extconf.rb ...

    package_ext_rb

    在Ruby编程语言中,`package_ext_rb`可能指的是一个用于扩展Ruby程序的打包脚本或模块。这个脚本通常会包含一系列操作,如编译...在实际开发中,理解如何正确地编写和构建这样的扩展是提升Ruby应用性能的关键技能之一。

    mruby-sqlite3

    1. `extconf.rb`:这是用于构建扩展模块的配置文件,它告诉 `mkmf`(Make Makefile for Ruby)如何编译和链接 `C` 代码。 2. `sqlite3.c` 和 `sqlite3.h`:这些是 SQLite3 的源码和头文件,提供了与数据库交互的函数...

    Fortran.rar_Fortran学习资料

    Fortran,全称为Formula Translation,是一种历史悠久的编程语言,尤其在科学计算和工程领域有着广泛的应用。本套学习资料旨在帮助新手快速入门Fortran编程,掌握其基本语法和高级特性。 1. **Fortran基础** - **...

    Rails bundle命令安装mysql gem包出错的解决方法

    在Ubuntu 12.04环境下,使用ruby-2.1.1版本,当尝试在新项目中运行`bundle install`时,会收到一条提示,要求先确保`gem install mysql2 -v '0.3.16'`能够成功执行。进一步查看日志文件,如`mkmf.log`,会发现错误...

    权志龙英语PPT学习教案.pptx

    【权志龙英语学习教案】是一个以韩国著名艺人权志龙(G-Dragon)为学习主题的专业课件,旨在结合他的个人经历、音乐成就以及英语学习元素,为学习者提供一个有趣且富有教育意义的学习资源。这个PPT教程可能包含了...

Global site tag (gtag.js) - Google Analytics