Ruby C Extension 排坑

3 篇文章 0 订阅

在编写OjRunner的过程中,一开始是参考了Tristan Penman’s Blog,在没有使用gem install之前,一切安好,但是gen install之后,也提示build native extension successfully,但是执行require 'oj_runner'之后报LoadError: cannot load such file -- oj_runner/oj_runner。这段代码是lib/oj_runner.rb中所有,目的是为了引入C编译之后的库。

先来看一下目录结构,红框中的文件是由我们创建的。源码写完之后会放到Github上去。
repository

首先我们来尝试直接加载

# now at ext/oj_runner
$ ruby extconf.rb
# generate extconf.h & Makefile & mkmf.log
$ make
# generate oj_runner.o & oj_runner.so
$ irb
> require 'oj_runner'
# => true
> OjRunner.run({})
# => 123

这样是没有问题的。再尝试RubyGems中通过添加-I参数的方法。

# now at project root
$ ruby -Ilib:ext -r oj_runner -e "puts OjRunner.run({})"
123

这样也没有问题,这是因为使用-I参数,相当于将lib和ext添加到了include path中,这样lib/oj_runner.rb中的require 'oj_runner/oj_runner'相当于查找到了ext/oj_runner/oj_runner.so,所以此时的问题并没有暴露出来。

先不管Gemfile和Rakefile中的内容,尝试通过gemspec文件将该测试包安装到gem中

# now at project root
$ gem build oj_runner.gemspec
$ sudo gem install oj_runner-0.0.2.gem
$ irb
> require 'oj_runner'
LoadError: cannot load such file -- oj_runner/oj_runner...

此时无法找到oj_runner/oj_runner,是因为即使ext也被安装到了gem里去,但是并没有被包含在路径中。查看gem包的安装路径的结构(我的是/var/lib/gems/2.3.0/gems/oj_runner-0.0.2),可以看到ext和lib下都有oj_runner.so,但显然ext并不是被找到的那个,lib下也有一个,但是被放错了位置。

tree1

那想,如果把require 'oj_runner/oj_runner'改为require 'oj_runner',可不可以。但因为同一个文件下存在oj_runner.rb和oj_runner.so,并不能正确的引用,导致出现undefined method 'run' for OjRunner:Class

仔细看了RubyGems,其中有一句

When the extension is built the files in ext/my_malloc/lib/ will be installed into the lib/ directory for you.

并且查阅了ruby-doc,由此得知,安装的时候会根据create_makefile中的target参数将编译生成的oj_runner.so拷贝到lib中的对应位置,因此原Tristan Penman’s Blog其实写错了extconf.rb文件,应该改为create_makefile('oj_runner/oj_runner')

tree2

或者把ext/extconf.rb中改为oj_runner_lib对应修改oj_runner.c中为Init_oj_runner_lib,这样就不会因为包名重复导致无法正确导入,并且可以得到下图的效果

irb
tree3

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值