Write Ruby methods using C (Part 1)

table of contents

Write Ruby methods using C (Part 1) <-Here Write Ruby methods using C (Part 2) Numo :: NArray

Introduction

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.

    1. will show you how to pass to simple variables such as double, float, int, 3. to pass to a string, and 4. to turn an existing library into an extended library. Please refer to (2) for how to pass an array.

1. Call a function provided by the compiler

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)

2. Call your own function

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)

3. Pass a string that calls your own function

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")

4. Make existing libraries available

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

Write Ruby methods using C (Part 1)
Write Ruby methods using C ++ (Part 2) Benchmark
Write Ruby methods using C (Numo :: NArray)
Write code using Ruby classes and instances
Ruby Learning # 15 Methods
About Ruby methods
Try using java.lang.Math methods
Try using Talend Part 2
Ruby Learning # 31 Object Methods
About Ruby instance methods
Ruby variables and methods
Try using Talend Part 1
[Ruby] methods, instance methods, etc ...
What you write in C # is written in Ruby like this
I wrote a C parser (like) using PEG in Ruby
Solving with Ruby, Perl and Java AtCoder ABC 129 C (Part 1)
Using Flutter on Ubuntu (Part 2)
Basic methods of Ruby hashes
Basic methods of Ruby arrays
Write class inheritance in Ruby
Try using Cocoa from Ruby
DB programming using EclipseLink part1
Creating a calendar using Ruby
Use C program from Ruby
Statically typed Ruby using Sorbet
Three Bit Manipulation Methods (Ruby)
Ruby C extension and volatile
Create a fortune using Ruby
What are Ruby class methods?
[Ruby] How to write blocks
Try using gRPC in Ruby
[Ruby] Singular methods and singular classes
[Ruby] Class methods, instance methods, etc.
Ruby variables and functions (methods)
Item 88: Write readObject methods defensively
Ruby methods and classes (basic)
[Programming Encyclopedia] ยง2 Try using Ruby
[Ruby] Singular methods and singular classes
Offline real-time how to write F03 ruby and C implementation example