Ruby の C拡張でモンキーパッチ(オープンクラス)

なんと、C拡張でモンキーパッチまで可能だとは!
ここが参考になりました。

前記事の C拡張をオープンクラスで実現します。Bundler を使っています。ソースは以下。

#include "utilsc.h"

long gcd(long x, long y) {
  long tmp;
  if (x < y) {tmp = x; x = y; y = tmp;}
  if (!y) return x;
  return gcd(y, x % y);
}

VALUE totient(VALUE self) {
  int a;
  long i, se;
  
  a = 0;
  se = FIX2LONG(self);
  for (i = 1; i < se; i++) {
    if (gcd(se, i) == 1) a++;
  }
  return INT2FIX(a);
}

void Init_utilsc(void){
  VALUE fix;
  
  fix = rb_const_get(rb_cObject, rb_intern("Fixnum"));
  rb_define_method(fix, "totient", totient, 0);
}

上は以下の Ruby コードとほぼ同等です。require 'utilsc' で実現します。utilsc はモジュールでも何でもないのですね。

class Fixnum
  def totient
    a = 0
    1.upto(self - 1) {|i| a += 1 if gcd(i) == 1}
    return a 
  end
end



サンプルコード。

require 'bundler/setup'
require 'utilsc'

2.upto(10) {|i| puts i.totient}



なお、GitHub で野良 Gem を作っているときに

Agent admitted failure to sign using the key.
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

というエラーがでました。これは

$ eval "$(ssh-agent -s)"
$ ssh-add ~/.ssh/id_rsa

パスフレーズを打ち込んで解決。

$ ssh -T git@github.com

で確認。

それから、野良Gem 作成はここがわかりやすい。