为了测试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'
#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); }
$ ruby extconf.rb $ make # 如果要安装至site-ruby $ make site-install
require 'foo.so' puts Foo.plus(3,4)
$ ruby test.rb 7