现在的位置: 首页 > 综合 > 正文

用C++写ruby扩展

2018年01月10日 ⁄ 综合 ⁄ 共 1696字 ⁄ 字号 评论关闭

用C++写ruby扩展

为了测试CDMA短信的发送方便,于是想到编译成lib,提供ruby使用。

SmsObject.h:
void SendSms(const char* msg, const char* number, char* out);

main.cpp:

//
// by deli 2009.6.11
//
#include <ruby.h>
#include "SmsObject.h"

static VALUE makepdu(VALUE self, VALUE arg1, VALUE arg2) {
    VALUE s;
    char pdu[512] = {0};
    char* msg = RSTRING(arg1)->ptr;
    char* number = RSTRING(arg2)->ptr;

    SendSms(msg, number, pdu);
    s = rb_str_new2(pdu);

    return s;
}

extern "C"
void __declspec(dllexport) Init_sms() {
    VALUE myModule = rb_define_module("CDMA");

    VALUE myClass =
        rb_define_class_under(myModule, "SMS", rb_cObject);

    int arg_count = 2;
    rb_define_method(myClass, "makepdu", RUBY_METHOD_FUNC(makepdu), arg_count);
}

注意: C++要加上RUBY_METHOD_FUNC, C不用加。不然就会出现类似的错误:
error C2664: ‘rb_define_method’ : cannot convert parameter 3 from
‘unsigned long (unsigned long,unsigned long,unsigned long)’ to ‘unsigned long (_
_cdecl *)(…)’
None of the functions with this name in scope match the target type

test.rb:

#!/usr/bin/ruby 

require 'sms'

include CDMA

obj = SMS.new
pdu = obj.makepdu('什么都可以想,什么都可以不想,便觉得是个自由的人', '15338896034')

puts pdu

D:\Ruby\ruby-serial\sms>ruby test.rb
0000021002040702c54ce225a8d008420003200000013220c27602724487ea9f7a772b079ff86276
02724487ea9f7a772a706b079ff8627dfc4e4afcbb317a71540f53a98bb42275d00501a70801c00d
0101

大概就是这样。

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

建立 extconf.rb

require 'mkmf'

$libs = '-lstdc++'
create_makefile 'foo'

建立 foo.cc

#include <ruby.h>

VALUE plus(VALUE self, VALUE va, VALUE vb)
{
	int a = NUM2INT(va);
	int b = NUM2INT(vb);

	return INT2NUM(a+b);
}

extern "C" void Init_foo()
{
	VALUE foo = rb_define_module("Foo");
	rb_define_module_function(foo, "plus", RUBY_METHOD_FUNC(plus), 2);
}

生成扩展 foo.so

$ ruby extconf.rb
$ make
# 如果要安装至site-ruby
$ make site-install

测试文件 test.rb

require 'foo.so'

puts Foo.plus(3,4)
$ ruby test.rb
7

抱歉!评论已关闭.