S.L Unit - 2
S.L Unit - 2
UNIT_II
⇒ Ruby was developed to make it aet as a sensild, buffer b/w human programmers & the
underling, computing machinery.
1. Extending Ruby: -
→ It is easy to extend Ruby with new features by Writing code in Ruby. Once you, start
adding in low-level code written in C, however the possibilities are endless.
Ruby objects in 𝑪:
→ Most Ruby objects are represented as (pointers to an area in memory that contains the
objects data of often implementation detail e.
→ In C code, all twee references are via variables of type value, so when you pass Ruby
objects around, you’ll do it by passing values.
→ This has one exception. For performance reasons. Ruby implements fixnums, symbols,
true, false and rill as so. called immediate values.
Creating an Extension:
1. Create the C source code file(s) in a given directory.
2. Create extconf. rb .
3. Run extconf. rb to create a Makefile for the C files in this directory.
4. Run make .
5. Run make install .
You may want to this if there is a particular important method you would like to
optimize with the speed of C, or if you would like to create an interface between a
C library and Ruby.
require 'mkmf'
create_header
create_makefile 'foobar'
Then run ruby extconf.rb which will create a few files for you (Makefile &
extconf.h). Don’t change these files.
Now create foobar.c, this name comes from the create_makefile line in extconf.rb.
You can change it if you want but it has to match your .c filename for this to work.
#include "ruby.h"
#include "extconf.h"
void Init_foobar()
{
// Your C code goes here
}
This is the basic skeleton of your C extension. Notice that you have to use the name
you declared on extconf.rb plus the word Init_. In this case Init_foobar.
void Init_foobar() {
VALUE mod = rb_define_module("RubyGuides");
rb_define_method(mod, "return_nil", rb_return_nil, 0);
}
You can use the rb_define_method method to attach the C function to this
module.
Now run make again to compile the extension, and try it like this:
require 'foobar'
include RubyGuides
print_hello
There you go, you just called a C function from Ruby!
Now if you expose this function to Ruby using rb_define_method you will get
a regular Ruby hash with one key (test) & a value of 1.
Don’t forget to recompile your extension every time you make changes.
Working with Strings
Your C functions can also take parameters.
For example:
VALUE rb_print_length(VALUE self, VALUE str) {
if (RB_TYPE_P(str, T_STRING) == 1) {
return rb_sprintf("String length: %ld", RSTRING_LEN(str));
}
return Qnil;
}
void Init_foobar()
{
rb_define_global_function("print_length", rb_print_length, 1);
}
Here we are taking a VALUE (ruby object) as an argument & then we make sure
it’s a string with the RB_TYPE_P macro. After that, we just print the string length
using the RSTRING_LEN macro.
If you want a pointer to the string data you can use the RSTRING_PTR macro.
Example:
VALUE rb_print_data(VALUE self, VALUE str) {
if (RB_TYPE_P(str, T_STRING) == 1) {
return rb_sprintf("String length: %s", RSTRING_LEN(str));
}
return Qnil;
}
Also notice how there is another parameter here, self, this is the object receiving
the method call.
If you want to define this method on the String class itself you would do it like this:
void Init_foobar()
{
rb_define_method(rb_cString, "print_length", rb_print_length, 0);
}
Working With Immediate Object: -
In 𝑐, we are used to working with a null-terminated string, Ruby strings, how war,
are more general a may well include embedded nulls.
Ruby string objects are actually references to an RString structure, & the Restring
structure contains both a length and pointer field. We can access the structure via
live Restring macros.
INT 2 NUM (int) → Fixnum or Bignum
When Values are not immediate, they are pointers to one of the predefined Ruby
object structures.
The structures for the basic built-in-classes are defined in ruby is & are named
RClassnames.
RArray, RBignum, RClass, RData, Rile, RFloat, RHash, Rbject, R Regexp, Resting &
Retract.
Ruby:
C:
Wraps the given (data type ptr, registers. The two garbage collection routines and
returns a value pointer to a genuine ruby object.
2. Value data –Make -structure (value class, C-type, voide (*Mask) (), void (*free) ()
(-type*)
-Allocates and sets to zero a structure of the indicated type first & then proceeds as Data -
wrap-street, C-trjpe is the name of data type that quire wrapping, not a variable of that type.
Ruby program:
𝑐𝑑 = 𝐶𝐷 player.new
the implementation of new in class is simple, if allocates memory for new object
then calls the object in initialize method to initialize that memory.
So, we need to implement an allocation functions and an initialize method.
C Extension (example.c):
#include "ruby.h"
typedef struct {
int x;
int y;
} Point;
Point *point;
point->x = NUM2INT(x);
point->y = NUM2INT(y);
return self;
Point *point;
return INT2NUM(point->x);
Point *point;
return INT2NUM(point->y);
Point *point;
point->x = NUM2INT(new_x);
return new_x;
Point *point;
point->y = NUM2INT(new_y);
return new_y;
void Init_example(void) {
rb_define_alloc_func(cExample, point_alloc);
Compilation:
# extconf.rb
require 'mkmf'
create_makefile('example')
ruby extconf.rb
make
# main.rb
require_relative 'example'
point.x = 30
point.y = 40
ruby main.rb
This example demonstrates how to create a Ruby C extension that wraps a C structure
(Point) and provides methods to manipulate its data.
Allocation Functions:
the allocation function in responsible for creating the memory used by object.
If the object implementing doesn't use any data other than Ruby instance variables,
Than you don't reed to write an allocation function -Ruby's default allocator roll
work just fine
But if you class wraps a (structure, you) need to allocate space for that structure in
the allocation function.
the allocation function gets passed the class of the object being allocated.
the allocation function crater am empty uninitialized object & we need to fill in
specific values
Cloning object:
All ruby objects can be copied using one of. two methods dup and clone. Both
produce a need instance of their receiver's class by? Calling the allocation function.
Then they copy across any instance variables from the original. clone than goes a
bit further and copies the singleton class and flags.
After copying the objects instance variables. the interpreter involves the new object
is initializing. copy method, passing in a reference to the original Object.
-To test the original object code (original) checks: → than a type of data and
Ruby, objects are instances of classes, and they are created using the new method of a class.
Additionally, Ruby provides a mechanism for cloning objects, allowing you to create a
duplicate with the same state as the original. Let's explore both aspects:
1. Object Creation:
a. Using the new method:
Objects in Ruby are created by instantiating a class using the new method.
Example:
go
Copy code
```ruby
class MyClass
def initialize(name)
@name = name
end
end
my_object = MyClass.new("Example")
b. Object Initialization:
The initialize method in a class is called when an object is created. It is used for
setting up initial state or performing any necessary setup.
go
```ruby
class Person
@name = name
@age = age
end
end
```
The initialize method here sets the name and age instance variables for the person
object during its creation.
2. Cloning Objects:
Ruby provides a clone method that creates a shallow copy of an object. The cloned
object is a duplicate, sharing the same class and initial state, but it has a separate
identity.
go
ruby
go
original_object = MyClass.new("Original")
cloned_object = original_object.clone
```
The dup method is similar to clone but creates a shallow copy without copying the
frozen state of the object.
go
```ruby
makefile
original_array = [1, 2, 3]
cloned_array = original_array.dup
```
3. Deep Copy:
If you need a deep copy, where nested objects are also duplicated, you might need to
implement a custom method or use a library like deep_cloneable or deep_dup.
go
```ruby
javascript
require 'deep_cloneable'
cloned_hash = original_hash.deep_clone
```
Libraries like deep_cloneable can provide a more comprehensive cloning mechanism for
complex objects.
Remember that cloning in Ruby might not always result in a true deep copy, especially for
complex objects or objects with references to other objects. Depending on your use case,
you may need to implement a custom clone method or use additional libraries for deep
copying
Allocates a ectype of c-type (not a variable) (of that (c-type) & casts the result to a
pointer of that type.
REALLOC-N (Var, c-type,n)
Reallocates n c-types and assigns the result to var, a pointer to a variable of type c-
type
type *ALLOCA-N(R-type,n)
Allocates memory for 𝑛 Objects of c-type on the stack - this memory will be auto
invokes ALLOCA-N returns.
Memory allocation is a fundamental concept in computer programming, including
scripting languages. It refers to the process of reserving and managing a region of a
computer's memory for a specific purpose, typically to store data during the execution of a
program. Memory allocation is crucial for dynamically managing data structures, objects,
variables, and other runtime entities.
In Ruby we rely lesson the type an object and more on it se capabilities. This known
as Duck typing..
Hence, Duck Typing means an object type is defined by what it can do not by what
it if duck typing refers to the tendency of Ruby to be less concerned with the class
of an object more concerned with what methods can be called on if twat operations
cam be performed on it.
In Ruby, we would use respond to 2 or might simply pass an object to a method
and know that on exception will be raised if it is used in appropriately.
It an object walks like advert and talks like a deck, then the Ruby interpreter is
happy to treats if as if if were a duck.
Eg :- #check, whether the object defines the...
to str method
⇒ true
⇒ false
⇒ false
The above example is 𝑥 a type of duck typing If an object quack like a duck (or) acts just
go ahead it treat it as a duck objects according to methods they define rather than the classes
from which they inherit or the modules They include.
Ruby is a dynamically-typed language with a strong and flexible type system. This means
that the type of a variable or object is determined and checked at runtime, and the language
provides a lot of flexibility in how variables and objects are used. Here are key aspects of
the Ruby type system:
1. Dynamic Typing:
Ruby is dynamically typed, meaning you don't have to declare the type of a variable when
you create it. The type is determined and can change during runtime.
go
```ruby
makefile
x = 10 # x is Fixnum
```
2. Strong Typing:
While Ruby is dynamically typed, it is also strongly typed. This means that the interpreter
enforces strict type rules, and implicit type conversions are limited.
go
```ruby
graphql
```
In the example above, Ruby does not automatically convert the string "10" to an integer
for the addition operation.
3. Object-Oriented:
Everything in Ruby is an object, including primitive data types like integers and booleans.
Objects encapsulate both data and behavior.
go
```ruby
perl
```
4. Type Coercion:
Ruby supports some level of automatic type coercion for common operations. For example,
it can automatically convert a Fixnum to a Float in a mathematical operation.
go
```ruby
makefile
```
5. NilClass:
Ruby has a special nil value, which represents the absence of a value. It is an instance of
the NilClass.
go
```ruby
go
x = nil
```
go
```ruby
ruby
```
7. Duck Typing:
Ruby follows the principle of "duck typing," where the type or the class of an object is less
important than the methods it responds to.
If an object quacks like a duck (responds to the expected methods), then it's treated as a
duck.
go
```ruby
ruby
def print_length(obj)
puts obj.length
end
```
8. Type Checking:
Ruby provides methods like is_a? and kind_of? for type checking.
go
```ruby
x = 42
```
9. Symbols:
go
```ruby
:symbol_name
```
The Ruby type system is designed to provide a balance between flexibility and reliability,
allowing developers to write expressive and concise code while still benefiting from the
advantages of a strongly typed language.
When you first look at some Ruby code, if will likely remind you of other
programming languages we have used.
this is because of the syntax is familiar to users of perl.python, and java etc,
c and 𝑐 + 𝑡;
→ Similarities with : as with 𝑐, in Ruby public private and protected dosimilar jobs.
Exceptions work in a Similar manner, through the keyword names have been
changed to protect the innocent.
Java:
pert docks are awesome -for those perter who 10ng for ekgant object oriented
feature ss builtin from the beginning. Ruby com help.
Similarities: As with Perl, in Ruby
parentheses are (bass) offer optional.
strings work basically the same.
PHP:
PHP is in widespread use for web applications. But if you want to use Ruby on rails
or just Want a language that's more fathered for general use. Ruby is worth a look.
Similarities: As in Php. in Ruby
Ruby is dynamically typed like in PHP. So you don’t need to worry about having
to declare Vanciblets.
This kind of hands off manipulation of Ruby programs from within c cock is easy
but it (interpreter if self. The call to ruby -init) has too major drawbacks. first, it is
indirect-we hare to keep storing things in global t extracting the values from these
global or et to use them.
second we (will) are not doing any real error checking. Which will definitely bite
us later. Co, the send way to interact with Ruby code is to use the (API).
this gives us much finer grained control also lets us handle errors.
we can do this by initializing the interpreter as normal, then, rather than evaluating
string instead invoke specific methods in your Ruby code.
when these methods. returns, your (code get) control back.
Embedded Ruby API
setup 𝑓 initializes the interpreter. This function be called before any other ruby-related
function.
Python:
there is good support for functional programming with first -class functions.
Anonymous functions and clotures.
(6) Embedding a Ruby Interpreter:
In addition to extending Ruby by adding 𝑐 code, you cars also turn the problem
around 𝑅 embed Ruby itself within your application.
We can interact Ruby by (API) or by evaluating strings
→ First we will interact by evaluating strings of Ruby code:
Initializes the $ : variable; necessary if your code loads any library modulus.
Void ruby - options (int, arg c, Shan ** argv):-
ruby_errinfo_print();
ruby_errinfo_clear();
}
VALUE my_variable = rb_str_new_cstr("Hello from C!");
rb_funcall(result, rb_intern("concat"), 1, my_variable);
ruby_cleanup(0);
return 0;
}
Remember that this is a basic example, and depending on your application, you
may need to handle more complex scenarios, manage memory properly, and handle
Ruby exceptions and errors appropriately