1

私はルビーネイティブ拡張を作成しようとするんだけど、私は私のプロジェクトをビルドし、test/の下で私のテストを実行するためにext/example_project/extconf.rbを使用するrakeを実行したときにテストが実行されたときに、私は次のエラーを取得します:ルビーネイティブ拡張:未定義のシンボル

./home/jbuesking/.rbenv/versions/2.3.0/bin/ruby: symbol lookup error: 
/home/jbuesking/repositories/example_project/lib/example_project/example_project.so: undefined symbol: some_function 

私は私のファイルが正しくリンクされて、私はいくつかの方法で私のextconf.rbおよび/またはRakefileを変更する必要がありますが、私はどのようにわからないことされていないかなり確信しています。

私は問題over on GitHubを示す簡単なリポジトリを作成しました。クローンして、プロジェクトルートからrakeを実行すると、同じエラーで失敗します。

いくつかの追加情報:

  • 私は失敗した機能は、サブディレクトリext/example_project/c_example_projectで定義された関数を呼び出すようにしようとしているsow example_project
  • を経由してプロジェクトを作成するためにルビーの宝石hoeを使用。私の実際のプロジェクトではext/example_projectディレクトリのgitサブモジュールを使用し、サブモジュールをサブディレクトリとして設定します。サブモジュールは、フラットな構造(ルートディレクトリのすべてのファイル)を持つcプロジェクトです。 注::その文句は混乱するかもしれませんが、キーポイントはext/example_project/c_example_projectで定義されたネストされたCプロジェクトがあり、私が呼び出そうとしているメソッドがあります。

明確化が必要な場合は教えてください。私はそれを提供するために最善を尽くします。

+0

これを行うには「ホー」よりも優れたものがあれば、私に教えてください。私は[チュートリアルを使って](https://tenderlovemaking.com/2009/12/18/writing-ruby-c-extensions-part-1.html)を打ち上げポイントとしていましたが、7年前ですそれ以来一緒に来てください! – JesseBuesking

答えて

2

ここで興味深い問題がいくつかあります。デフォルトでは、mkmfは実際にソースを構築するために複数のディレクトリを指定することをサポートしていません。

https://www.ruby-forum.com/topic/4224640

基本的に、あなた自身のファイルを自分のextconf.rb$objsグローバルを構築:

は(OBJS設定について武宏久保さんのコメント)ここに見られるように、回避策があります。

は、あなたのgithubのコードを使用して、ここで私はextconf.rbはに加えて、

EXTCONFを動作するようになったものです。RB

globs = [".", "c_example_project"].map do |directory| 
    File.join(File.dirname(__FILE__), directory) 
end.join(",") 

$objs = Dir.glob("{#{globs}}/*.c").map do |file| 
    File.join(File.dirname(file), "#{File.basename(file, ".c")}.o") 
end 

私は実際に私達はちょうど{.,c_example_project}/*.cでグロブた場合レーキ、コンパイラはextconf.rbはを実行していると思われることから、怖がられたいくつかの理由で、Cソースのそれぞれに絶対パスを構築していますお知らせファイルを別のディレクトリから取得します。

さらに、テスト/ c拡張子にはいくつかのエラーがあります。 example_project.c修正で、以下の変更を行うテストの失敗:

static VALUE example_project_c_code_function() 
{ 
- return some_function(); 
+ VALUE _string = rb_str_new2(some_function()); 
+ int _enc = rb_enc_find_index("UTF-8"); 
+ rb_enc_associate_index(_string, _enc); 
+ return _string; 
} 

説明

は基本的に、あなたのextconf.rbは内c_example_project.hヘッダをチェックしているにもかかわらず、あなたが実際に生成していませんオブジェクトファイルsome_functionが定義されています。したがって、最終的な動的ライブラリをリンクするときに、rubyがロードされると、some_functionの定義がなくなり、エラーが発生します。

+0

恐ろしい!ええ、問題は、ファイルが正しくコンパイルされてリンクされていないと思っていました。私はその作業をどうやって行うのか分かりませんでした。何が必要なのか把握していただきありがとうございます! – JesseBuesking

0

ネイティブ拡張を構築する経験はありませんが、mkmfソースコードからは、ソースディレクトリを1つしか指定できないようです。両方のファイルをc_example_projectから親ディレクトリに移動し、すべてが正しくリンクされていました。私はそれがあなたがそれをやるべきだと思います。すべての一般的な宝石(pg、nokogiriなど)にはこのようなコード構造があり、* .cと* .hファイルはすべて1つのディレクトリにあります。

自分でMakefileを作成することはできますが、維持するにはあまりにも多くの作業が必要です。

PS。あなたのプロジェクトは正常にコンパイルされましたが、セグメンテーションフォールトがあります。文字列へのポインタではなく、some_functionに適切なルビ文字列オブジェクトを返さなければならないからです。

+0

私はgitサブモジュールを使用できなくなり、代わりに手作業でファイルをコピーする必要があるということを意味するので、ファイルをディレクトリの上に移動することを含まないソリューションを期待していました。私はそこに良い解決策があると思っていますが、あなたのことを受け入れるでしょう。 – JesseBuesking

関連する問題