Write Ruby methods using C (Part 1) <-Here Write Ruby methods using C (Part 2) Numo :: NArray
Please refer to "Writing Ruby methods using C ++ (Part 1)" for how to write a Ruby extension library in C ++. .. If you write C ++, you can create a library with almost no effort, so if you write it from scratch, I recommend that.
Here, I will introduce how to make a function written in C into an extension library. You can write in C ++ in the same way as in C, so you can use it even if you already have a library written in C.
Write a SWIG interface definition file. In% {..%} above, read the header file or write the equivalent of the header file.
test.i
%module test //Module name The first letter is converted to uppercase
%{
#include <math.h>
%}
%include "typemaps.i"
extern double floor(double x);
// double modf(double value, double *iptr);When receiving a value with a pointer*Change to OUTPUT
extern double modf(double value, double *OUTPUT);
At the bottom, I write a function to call from Ruby. There are many function headers in math.h, but we will make floor and modf available from Ruby. The second argument to modf is a pointer and returns a double value. Input, output, and input / output are possible with pointers, and each function can be given by writing * INPUT, * OUTPUT, * INOUT.
extconf.rb
require 'mkmf'
create_makefile("test") #Same as the module name
A Ruby program for creating Makefike.
Put the above files in the same folder and execute the following command.
swig -ruby test.i
ruby extconf.rb
make
This completes test.bundle (extension depends on the OS). This is a test program.
test1.rb
require "./test"
p Test.floor(2.3)
p Test. modf(2.3)
I wrote a function that passes a simple variable. It's just a normal C function. A function that returns twice the value. I don't use pointers.
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);
I haven't created a header file, so write the equivalent of the header file in% {..%}. Use the same extconf.rb file and commands as above. If there are program files such as .c and .cpp in the folder, we will compile and link them all, so be careful not to include unnecessary files.
This is a test program.
test2.rb
require "./test"
p Test.twicefold_d(3.4)
Strings can also be easily passed to the function.
test3.c
#include "test3.h"
int string_length(char* str){
return(strlen(str));
}
test3.h
#include <string.h>
int string_length(char* str);
Here, we are creating a header file. It doesn't take much time, so I think it's more convenient to create a header file.
test.i
%module test
%{
#include "test3.h"
%}
%include test3.h
Similarly, use the same extconf.rb file and commands as above.
test1.rb
require "./test"
p Test.string_length("abcd")
Enables the GSL functions gsl_hypot and gsl_hypot3. It reads the GSL header file and defines the interface for the two functions. The two functions are just copied from the header file and have not changed.
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.link so
create_makefile("test")
I need to link the GSL header file reading and libgsl.so, so I've added three lines for that. The command is often the same as above, but if you don't know the location of the header file and libgsl.so, write the path later in ruby extconf.rb as follows:
ruby extconf.rb -- --with-gsl-dir=/path
--with-gsl-include=/path/include
--with-gsl-lib=/path/lib
When files are in locations like /path/include/gsl/gsl_math.h and /path/lib/libgsl.so You can specify both at once with --with-gsl-dir = / path. The bottom two can be specified one by one.
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