Ecrire des méthodes Ruby en utilisant C (Partie 1) <-Here Écrire des méthodes Ruby en utilisant C (Partie 2) Numo :: NArray
Reportez-vous à "Ecrire des méthodes Ruby en C ++ (Partie 1)" pour savoir comment écrire une bibliothèque d'extension Ruby en C ++. .. Si vous écrivez C ++, vous pouvez créer une bibliothèque presque sans effort, donc si vous l'écrivez à partir de zéro, je le recommande.
Ici, nous allons vous montrer comment transformer une fonction écrite en C en une bibliothèque d'extensions. Vous pouvez écrire en C ++ de la même manière qu'en C, vous pouvez donc l'utiliser même si vous avez déjà une bibliothèque écrite en C.
Écrivez un fichier de définition d'interface SWIG. Dans% {..%} ci-dessus, lisez le fichier d'en-tête ou écrivez l'équivalent du fichier d'en-tête.
test.i
%module test //Nom du module La première lettre est convertie en majuscule
%{
#include <math.h>
%}
%include "typemaps.i"
extern double floor(double x);
// double modf(double value, double *iptr);Lors de la réception d'une valeur avec un pointeur*Changer pour OUTPUT
extern double modf(double value, double *OUTPUT);
En bas, j'écris une fonction à appeler depuis Ruby. Il existe de nombreux en-têtes de fonctions dans math.h, mais nous rendrons floor et modf disponibles à partir de Ruby. Le deuxième argument de modf est un pointeur et renvoie une valeur de type double. L'entrée, la sortie et l'entrée / sortie sont possibles avec le pointeur, et chaque fonction peut être donnée en écrivant * INPUT, * OUTPUT, * INOUT.
extconf.rb
require 'mkmf'
create_makefile("test") #Identique au nom du module
Un programme Ruby pour créer Makefike.
Placez les fichiers ci-dessus dans le même dossier et exécutez la commande suivante.
swig -ruby test.i
ruby extconf.rb
make
Ceci termine test.bundle (l'extension dépend du système d'exploitation). Ceci est un programme de test.
test1.rb
require "./test"
p Test.floor(2.3)
p Test. modf(2.3)
J'ai écrit une fonction qui passe une simple variable. C'est juste une fonction C normale. Une fonction qui renvoie deux fois la valeur. Je n'utilise pas de pointeurs.
test2.c
double twicefold_d(double x){
return(x*2.0);
}
test.i
%module test
%{
double twicefold_d(double x);
%}
double twicefold_d(double x);
Je n'ai pas créé de fichier d'en-tête, alors écrivez l'équivalent du fichier d'en-tête dans% {..%}. Utilisez le même fichier extconf.rb et les mêmes commandes que ci-dessus. S'il y a des fichiers programme tels que .c et .cpp dans le dossier, nous essaierons de tous les compiler et de les lier, alors faites attention à ne pas inclure de fichiers inutiles.
Ceci est un programme de test.
test2.rb
require "./test"
p Test.twicefold_d(3.4)
Les chaînes peuvent également être facilement transmises à la fonction.
test3.c
#include "test3.h"
int string_length(char* str){
return(strlen(str));
}
test3.h
#include <string.h>
int string_length(char* str);
Ici, nous créons un fichier d'en-tête. Cela ne prend pas beaucoup de temps, donc je pense qu'il est plus pratique de créer un fichier d'en-tête.
test.i
%module test
%{
#include "test3.h"
%}
%include test3.h
De même, utilisez le même fichier extconf.rb et les mêmes commandes que ci-dessus.
test1.rb
require "./test"
p Test.string_length("abcd")
Active les fonctions GSL gsl_hypot et gsl_hypot3. Il lit le fichier d'en-tête GSL et définit l'interface entre les deux fonctions. Les deux fonctions sont simplement copiées à partir du fichier d'en-tête et n'ont pas changé.
test.i
%module test
%{
#include "gsl/gsl_math.h"
%}
extern double gsl_hypot(const double x, const double y);
extern double gsl_hypot3(const double x, const double y, const double z);
extconf.rb
require 'mkmf'
dir_config("gsl")
have_header("gsl/gsl_math.h")
have_library("gsl") # libgsl.lien donc
create_makefile("test")
J'ai besoin de lier la lecture du fichier d'en-tête GSL et libgsl.so, j'ai donc ajouté trois lignes pour cela. La commande est souvent la même que ci-dessus, mais si vous ne connaissez pas l'emplacement du fichier d'en-tête et de libgsl.so, écrivez le chemin plus tard dans ruby extconf.rb comme suit:
ruby extconf.rb -- --with-gsl-dir=/path
--with-gsl-include=/path/include
--with-gsl-lib=/path/lib
Lorsque les fichiers se trouvent à des emplacements tels que /path/include/gsl/gsl_math.h et /path/lib/libgsl.so Vous pouvez spécifier les deux à la fois avec --with-gsl-dir = / path. Les deux derniers peuvent être spécifiés un par un.
test4.rb
require "./test"
p Test.gsl_hypot(3, 4)
p Test.gsl_hypot3(3, 4, 5)
CentOS 8.2 / Ruby 2.6.6 / Swig 3.0.12 macOS 10.13.6 / Ruby 2.7.1 / Swig 4.0.2
Recommended Posts