1

Ich versuche, eine ruby ​​native Erweiterung zu erstellen, aber wenn ich rake ausführen, die ext/example_project/extconf.rb verwendet, um mein Projekt zu erstellen und meine Tests unter test/ auszuführen, erhalte ich den folgenden Fehler, wenn die Tests ausgeführt werden:ruby ​​nativen Erweiterung: undefined Symbol

./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 

ich bin mir ziemlich sicher sind meine Dateien nicht korrekt verbunden ist und dass ich meine extconf.rb und/oder Rakefile in irgendeiner Weise zu ändern, aber ich bin nicht sicher, wie.

Ich habe ein einfaches Repository erstellt, das das Problem over on GitHub zeigt. Es wird mit demselben Fehler fehlschlagen, wenn Sie es klonen und rake aus dem Projektstamm ausführen.

Einige zusätzliche Informationen:

  • verwendete ich die Ruby Gem hoe das Projekt über sow example_project
  • Die Fehler-Funktion eine Funktion im Unterverzeichnis ext/example_project/c_example_project definiert aufzurufen versucht, zu erstellen. Mein aktuelles Projekt verwendet ein git-Submodul aus dem Verzeichnis ext/example_project, das wiederum das Submodul als Unterverzeichnis einrichtet. Das Submodul ist ein c-Projekt mit einer abgeflachten Struktur (alle Dateien im Stammverzeichnis). Hinweis: Diese Formulierung kann verwirrend sein, aber der entscheidende Punkt ist, dass es ein verschachteltes c-Projekt gibt, das unter ext/example_project/c_example_project definiert ist und Methoden enthält, die ich aufrufen möchte.

Lassen Sie mich wissen, wenn eine Klärung erforderlich ist, und ich werde mein Bestes tun, um es zu liefern.

+0

Nur ein Follow-up, wenn es etwas Besseres als 'Hacke' dafür gibt, lass es mich wissen. Ich war [ein Tutorial] (https://tenderlovemaking.com/2009/12/18/writing-ruby-c-extensions-part-1.html) als Startpunkt, aber es ist 7 Jahre alt, also vielleicht etwas besseres Komm seither mit! – JesseBuesking

Antwort

2

So, es gibt einige interessante Probleme, die Sie hier haben. Standardmäßig unterstützt mkmf nicht die Angabe mehrerer Verzeichnisse zum Erstellen von Quellen.

Es gibt ein Problem zu umgehen, wie hier zu sehen (Takehiro Kubo Kommentar über die Einstellung objs):

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

Grundsätzlich Sie die $objs global in Ihrer extconf.rb Datei selbst konstruieren.

Ihre Github Code verwenden, hier ist was ich zu dem extconf.rb hinzugefügt und bekam

extconf zu arbeiten.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 

Hinweis Ich Konstruktion tatsächlich einen absoluten Pfad zu jedem der C-Quellen, aus irgendeinem Grund Rake-Compiler wurde ausgeflippt, wenn wir nur mit {.,c_example_project}/*.c Globbing wurden, vermutlich, da sie die extconf.rb läuft Datei aus einem anderen Verzeichnis.

Zusätzlich haben Ihre Tests/c-Erweiterungen ein paar Fehler in ihnen. Macht die folgende Änderung in example_project.c den Testfehler behebt:

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; 
} 

Erklärung

Grundsätzlich obwohl Sie den c_example_project.h Header in Ihrem extconf.rb sind prüfen, sie ist nicht wirklich Erzeugen der Objektdatei, in der some_function definiert ist. Wenn also die letzte dynamische Bibliothek, die ruby ​​lädt, verlinkt wird, gibt es keine Definition für some_function und Sie erhalten Ihren Fehler.

+0

Super! Ja, ich dachte, das Problem sei, dass die Dateien nicht korrekt kompiliert und verlinkt würden, ich hatte einfach keine Ahnung, wie ich das machen sollte. Danke, dass Sie herausgefunden haben, was getan werden muss! – JesseBuesking

0

Ich habe keine Erfahrung mit dem Erstellen nativer Erweiterungen, aber von mkmf Quellcode sieht es so aus, als ob Sie nur ein Quellverzeichnis angeben können. Ich habe beide Dateien von c_example_project in das übergeordnete Verzeichnis verschoben und alles wurde ordnungsgemäß verknüpft. Ich denke, so solltest du es tun. Alle gängigen Edelsteine ​​(wie pg, nokogiri usw.) haben eine solche Codestruktur, alle * .c und * .h Dateien befinden sich in einem Verzeichnis.

Sie können immer Makefile selbst erstellen, aber das würde zu viel Arbeit erfordern.

PS. Ihr Projekt wurde erfolgreich kompiliert, aber Sie haben einen Segmentierungsfehler, weil Sie in some_function das richtige Ruby-String-Objekt und nicht den Zeiger auf eine Zeichenfolge zurückgeben sollten.

+0

Ich habe auf eine Lösung gehofft, bei der die Dateien nicht in ein Verzeichnis verschoben wurden, da ich dann das git Submodul nicht mehr verwenden kann und stattdessen auf das manuelle Kopieren von Dateien angewiesen bin ... wenn niemand eine bessere Antwort hinterlässt Ich akzeptiere deins, obwohl ich hoffe, dass es eine bessere Lösung gibt. – JesseBuesking

Verwandte Themen