└── README.md /README.md: -------------------------------------------------------------------------------- 1 | ## Getting started 2 | 3 | ### 1. Your gem skeleton 4 | 5 | $ bundle gem my_awesome_gem 6 | $ cd my_awesome_gem 7 | $ mkdir -p ext/my_awesome_gem 8 | 9 | ### 2. Teaching Rake how to compile your gem 10 | 11 | `my_awesome_gem/my_awesome_gem.gemspec` 12 | 13 | spec.add_development_dependency "rake-compiler" 14 | 15 | `my_awesome_gem/Rakefile` 16 | 17 | require "rake/extensiontask" 18 | 19 | Rake::ExtensionTask.new("my_awesome_gem") do |ext| 20 | ext.lib_dir = "lib/my_awesome_gem" 21 | end 22 | 23 | ### 3. Boilerplate 24 | 25 | `my_awesome_gem/ext/my_awesome_gem/extconf.rb` 26 | 27 | require 'mkmf' 28 | create_makefile('my_awesome_gem') 29 | 30 | `my_awesome_gem/ext/my_awesome_gem/my_awesome_gem.c` 31 | 32 | #include "ruby.h" 33 | 34 | VALUE MyAwesomeGemModule = Qnil; 35 | 36 | void Init_my_awesome_gem() 37 | { 38 | MyAwesomeGemModule = rb_define_module("MyAwesomeGem"); 39 | rb_init_awesome_class(); 40 | } 41 | 42 | ### 4. Your first class 43 | 44 | `my_awesome_gem/ext/my_awesome_gem/my_awesome_gem.c` 45 | 46 | #include "ruby.h" 47 | #include "awesome_class.h" 48 | 49 | // ... 50 | 51 | void Init_my_awesome_gem() 52 | { 53 | MyAwesomeGemModule = rb_define_module("MyAwesomeGem"); 54 | rb_init_awesome_class(); 55 | } 56 | 57 | 58 | `my_awesome_gem/ext/my_awesome_gem/awesome_class.h` 59 | 60 | #include "ruby.h" 61 | void rb_init_awesome_class(); 62 | 63 | `my_awesome_gem/ext/my_awesome_gem/awesome_class.c` 64 | 65 | #include "awesome_class.h" 66 | 67 | VALUE AwesomeClass = Qnil; 68 | extern VALUE MyAwesomeGemModule; 69 | 70 | void rb_init_awesome_class() 71 | { 72 | AwesomeClass = rb_define_class_under(MyAwesomeGemModule, "AwesomeClass", rb_cObject); 73 | } 74 | 75 | ### 5. Your first instance method 76 | 77 | `my_awesome_gem/ext/my_awesome_gem/awesome_class.h` 78 | 79 | #include "ruby.h" 80 | void rb_init_awesome_class(); 81 | VALUE rb_awesome_class_say_hi(VALUE self); 82 | VALUE rb_awesome_class_say_hi_to(VALUE self, VALUE r_name); 83 | 84 | `my_awesome_gem/ext/my_awesome_gem/awesome_class.c` 85 | 86 | #include "awesome_class.h" 87 | 88 | VALUE AwesomeClass = Qnil; 89 | extern VALUE MyAwesomeGemModule; 90 | 91 | void rb_init_awesome_class() 92 | { 93 | AwesomeClass = rb_define_class_under(MyAwesomeGemModule, "AwesomeClass", rb_cObject); 94 | rb_define_method(AwesomeClass, "say_hi", rb_awesome_class_say_hi, 0); 95 | rb_define_method(AwesomeClass, "say_hi_to", rb_awesome_class_say_hi, 1); 96 | } 97 | 98 | VALUE rb_awesome_class_say_hi(VALUE self) 99 | { 100 | return rb_str_new2("Hello!"); 101 | } 102 | 103 | VALUE rb_awesome_class_say_hi_to(VALUE self, VALUE r_name) 104 | { 105 | VALUE r_greeting = rb_str_new2("Hello, "); 106 | rb_str_append(r_greeting, r_name); 107 | rb_str_append(r_greeting, INT2NUM(33)); 108 | 109 | return r_greeting; 110 | } 111 | 112 | ### 6. Including your new class 113 | 114 | `my_awesome_gem/lib/my_awesome_gem.rb` 115 | 116 | require 'my_awesome_gem/my_awesome_gem' 117 | 118 | ### 7. Compiling 119 | 120 | $ rake clean compile 121 | 122 | ## Modules and Classes 123 | 124 | ### rb_define_module(`module_name`) 125 | 126 | Defines the module named `module_name`. 127 | 128 | VALUE AwesomeNewModule = rb_define_module("Awesome"); 129 | 130 | ### rb_define_module_function(`ruby_module`, `method_name`, `implementation`, `argc`) 131 | 132 | Defines a function called `method_name` under the module `ruby_module`. Expects `argc` arguments and calls `implementation` when invoked in Ruby. 133 | 134 | VALUE rb_module_say_hi(VALUE klass) 135 | { 136 | VALUE r_hello = rb_str_new2("Hello!"); 137 | return r_hello; 138 | } 139 | 140 | void Init_example() 141 | { 142 | VALUE AwesomeNewModule = rb_define_module("Awesome"); 143 | rb_define_module_function(AwesomeNewModule, "say_hi", rb_module_say_hi, 0); 144 | } 145 | 146 | ### rb_define_const(`ruby_module_or_class`, `constant_name`, `value`) 147 | 148 | Defines a constant under the Ruby Module or Class `ruby_module_or_class` with the name `constant_name` and value `value`. 149 | 150 | void Init_example() 151 | { 152 | VALUE AwesomeNewModule = rb_define_module("Awesome"); 153 | rb_define_const(AwesomeNewModule, "UNIVERSAL_ANSWER", INT2NUM(42)); 154 | } 155 | 156 | ### rb_define_class_under(`ruby_module`, `class_name`, `super_class`) 157 | 158 | Defines a class under the Ruby module `ruby_module` called `class_name` and inheriting from `super_class`. 159 | 160 | void Init_example() 161 | { 162 | VALUE AwesomeNewModule = rb_define_module("Awesome"); 163 | rb_define_module_function(AwesomeNewModule, "say_hi", rb_module_say_hi, 0); 164 | 165 | VALUE AwesomeClass = rb_define_class_under(AwesomeNewModule, "AwesomeClass", rb_cObject); 166 | } 167 | 168 | ### rb_define_singleton_method(`ruby_class`, `method_name`, `implementation`, `argc`) 169 | 170 | Defines a class method called `method_name` under the class `ruby_class`. Expects `argc` arguments and calls `implementation` when invoked in Ruby. 171 | 172 | VALUE rb_class_say_hi(VALUE klass) 173 | { 174 | VALUE r_hello = rb_str_new2("Hello!"); 175 | return r_hello; 176 | } 177 | 178 | void Init_example() 179 | { 180 | VALUE AwesomeNewModule = rb_define_module("Awesome"); 181 | VALUE AwesomeClass = rb_define_class_under(AwesomeNewModule, "AwesomeClass", rb_cObject); 182 | 183 | rb_define_singleton_method(AwesomeClass, "say_hi", rb_class_say_hi, 0); 184 | } 185 | 186 | 187 | ### rb_define_method(`ruby_class`, `method_name`, `implementation`, `argc`) 188 | 189 | Defines an instance called `method_name` under the class `ruby_class`. Expects `argc` arguments and calls `implementation` when invoked in Ruby. 190 | 191 | VALUE rb_class_say_hi(VALUE klass) 192 | { 193 | VALUE r_hello = rb_str_new2("Hello!"); 194 | return r_hello; 195 | } 196 | 197 | void Init_example() 198 | { 199 | VALUE AwesomeNewModule = rb_define_module("Awesome"); 200 | VALUE AwesomeClass = rb_define_class_under(AwesomeNewModule, "AwesomeClass", rb_cObject); 201 | 202 | rb_define_method(AwesomeClass, "say_hi", rb_class_say_hi, 0); 203 | } 204 | 205 | ### rb_ivar_set(`ruby_object`, `ivar_name`, `value`) 206 | 207 | Sets the instance variable `ivar_name` into the object `ruby_object` 208 | 209 | rb_ivar_set(self, rb_str_new2("@universal_answer"), INT2NUM(42)); 210 | 211 | ### rb_ivar_get(`ruby_object`, `ivar_name`) 212 | 213 | Gets the instance variable `ivar_name` from the object `ruby_object` 214 | 215 | VALUE r_universal_answer = rb_ivar_get(self, rb_str_new2("@universal_answer")); 216 | // => 42 217 | 218 | 219 | ## Strings 220 | 221 | ### rb_str_new(`c_string`, `length`) 222 | 223 | Creates a new Ruby string with the value `c_string` and length `length`. 224 | 225 | char *message = "Hello, World!"; 226 | VALUE r_message = rb_str_new(message, 13); 227 | 228 | ### rb_str_new2(`c_string`) 229 | 230 | Creates a new Ruby string with the value `string`. Length is inferred from the string, as long as it is [null terminated](http://c.learncodethehardway.org/book/ex9.html). 231 | 232 | char *message = "Hello, World!"; 233 | VALUE r_message = rb_str_new2(message); 234 | // => Hello, World! 235 | 236 | 237 | ### rb_str_dup(`ruby_string_object`) 238 | 239 | Creates a copy from a Ruby String object. 240 | 241 | char *message = "Hello, World!"; 242 | VALUE r_message = rb_str_new2(message); 243 | VALUE r_message_copy = rb_str_dup(r_message); 244 | // => Hello, World! 245 | 246 | 247 | ### rb_str_plus(`ruby_string_object_1`, `ruby_string_object_2`) 248 | 249 | Concatenates two Ruby String objects, returning a new Ruby String as a result. 250 | 251 | VALUE r_hello = rb_str_new2("Hello"); 252 | VALUE r_world = rb_str_new2(", World!"); 253 | VALUE r_hello_world = rb_str_plus(r_hello, r_world); 254 | // => Hello, World! 255 | 256 | ### rb_str_times(`ruby_string_object`, `ruby_fixnum_object`) 257 | 258 | Repeats a Ruby String `ruby_fixnum_object` times. 259 | 260 | VALUE r_times = INT2NUM(16); 261 | VALUE r_string = rb_str_new2("Na"); 262 | VALUE r_result = rb_str_times(r_string, r_times); 263 | VALUE r_batman = rb_str_plus(r_result, rb_str_new2(" Batman")); 264 | // => NaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNa Batman! 265 | 266 | ### rb_str_substr(`ruby_string_object`, `begin`, `length`) 267 | 268 | Grabs a substring of a Ruby String object, starting at `begin` with `length` characters. 269 | 270 | VALUE r_hello_world = rb_str_new2("Hello, World!"); 271 | VALUE r_hello = rb_str_substr(r_hello_world, 0, 5); 272 | // => Hello 273 | 274 | ### rb_str_cat(`ruby_string_object`, `c_string`, `length`) 275 | 276 | Takes the `c_string`'s first `length` characters and appends it to an existing Ruby String. 277 | 278 | VALUE r_batman = rb_str_times(rb_str_new2("Na"), INT2NUM(16)); 279 | rb_str_cat(r_batman, " Batman!", 8); 280 | // => NaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNa Batman! 281 | 282 | 283 | ### rb_str_cat2(`ruby_string_object`, `c_string`) 284 | 285 | Takes the `c_string` and appends it to an existing Ruby String. Length is inferred from the string, as long as it is [null terminated](http://c.learncodethehardway.org/book/ex9.html). 286 | 287 | VALUE r_batman = rb_str_times(rb_str_new2("Na"), INT2NUM(16)); 288 | rb_str_cat2(r_batman, " Batman!"); 289 | // => NaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNa Batman! 290 | 291 | ### rb_str_append(`ruby_string_object_1`, `ruby_string_object_2`) 292 | 293 | Appends `ruby_string_object_2` into `ruby_string_object_1`. 294 | 295 | VALUE r_batman = rb_str_times(rb_str_new2("Na"), INT2NUM(16)); 296 | rb_str_append(r_batman, rb_str_new2(" Batman!")); 297 | // => NaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNa Batman! 298 | 299 | ### rb_str_concat(`ruby_string_object`, `ruby_object`) 300 | 301 | Concatenates `ruby_object` into `ruby_string_object`. If `ruby_object` is a Fixnum between 0 and 255, then it is converted to a character before it is copied. Otherwise, this function behaves exactly the same as `rb_str_append`. 302 | 303 | VALUE r_dull_hello_world = rb_str_new2("Hello, World"); 304 | rb_str_concat(r_dull_hello_world, INT2NUM(33)); 305 | // => Hello, World! 306 | 307 | ### StringValueCStr(`ruby_string_object`) 308 | 309 | Takes a Ruby String object and converts it to a NULL terminated `char *` 310 | 311 | VALUE r_hello_world = rb_str_new2("Hello, World!"); 312 | char *hello_world = StringValueCStr(r_hello_world); 313 | // => Hello, World! 314 | 315 | ## Arrays 316 | 317 | ### rb_ary_new() 318 | 319 | Creates a new Ruby Array object with 0 elements. 320 | 321 | VALUE r_boring_empty_ary = rb_ary_new(); 322 | // => [] 323 | 324 | ### rb_ary_new2(`size`) 325 | 326 | Creates a new Ruby Array object with `size` elements. 327 | 328 | VALUE r_array = rb_ary_new2(10); 329 | 330 | ### rb_ary_store(`ruby_array`, `index`, `value`) 331 | 332 | Stores `value` (a Ruby object) on the index `index` in the array `ruby_array`. 333 | 334 | VALUE r_array = rb_ary_new2(1); 335 | rb_ary_store(r_array, 0, rb_str_new2("Hello!")); 336 | // => ["Hello!"] 337 | 338 | ### rb_ary_push(`ruby_array`, `value`) 339 | 340 | Stores `value` (a Ruby object) at the end of the array `ruby_array`. 341 | 342 | VALUE r_array = rb_ary_new2(1); 343 | rb_ary_push(r_array, rb_str_new2("Hello!")); 344 | // => ["Hello!"] 345 | 346 | ### rb_ary_unshift(`ruby_array`, `value`) 347 | 348 | Stores `value` (a Ruby object) at the beginning of the array `ruby_array`. 349 | 350 | VALUE r_array = rb_ary_new2(2); 351 | rb_ary_push(r_array, rb_str_new2("World!")); 352 | rb_ary_unshift(r_array, rb_str_new2("Hello")); 353 | // => ["Hello", "World!"] 354 | 355 | ### rb_ary_pop(`ruby_array`) 356 | 357 | Removes the last element off of the array `ruby_array` and returns it. 358 | 359 | VALUE r_array = rb_ary_new2(2); 360 | rb_ary_push(r_array, rb_str_new2("Hello")); 361 | rb_ary_push(r_array, rb_str_new2("World!")); 362 | VALUE r_world = rb_ary_pop(r_array); 363 | // => World! 364 | 365 | ### rb_ary_shift(`ruby_array`) 366 | 367 | Removes the first element off of the array `ruby_array` and returns it. 368 | 369 | VALUE r_array = rb_ary_new2(2); 370 | rb_ary_push(r_array, rb_str_new2("Hello")); 371 | rb_ary_push(r_array, rb_str_new2("World!")); 372 | VALUE r_hello = rb_ary_shift(r_array); 373 | // => Hello 374 | 375 | ### rb_ary_entry(`ruby_array`, `index`) 376 | 377 | Returns the array entry at index `index` 378 | 379 | VALUE r_array = rb_ary_new2(2); 380 | rb_ary_push(r_array, rb_str_new2("Hello")); 381 | rb_ary_push(r_array, rb_str_new2("World!")); 382 | VALUE r_hello = rb_ary_entry(r_array, 0); 383 | // => Hello 384 | 385 | ### rb_ary_dup(`ruby_array`) 386 | 387 | Creates and returns a copy of the array `ruby_array`. 388 | 389 | VALUE r_array = rb_ary_new2(2); 390 | rb_ary_push(r_array, rb_str_new2("Hello")); 391 | rb_ary_push(r_array, rb_str_new2("World!")); 392 | 393 | VALUE r_array_copy = rb_ary_dup(r_array); 394 | // => ["Hello", "World!"] 395 | 396 | ### rb_ary_to_s(`ruby_array`) 397 | 398 | Invokes the `to_s` on the array. 399 | 400 | VALUE r_array = rb_ary_new2(2); 401 | rb_ary_push(r_array, rb_str_new2("Hello")); 402 | rb_ary_push(r_array, rb_str_new2("World!")); 403 | VALUE r_array_str = rb_ary_to_s(r_array); 404 | # => "[\"Hello\", \"World!\"]" 405 | 406 | ### rb_ary_join(`ruby_array`, `ruby_string_object`) 407 | 408 | Creates a Ruby String by converting the elements of the array `ruby_array` to Strings and joining them by `ruby_string_object`. If `Qnil` is passed, then no separator is used. 409 | 410 | VALUE r_array = rb_ary_new2(2); 411 | rb_ary_push(r_array, rb_str_new2("Hello")); 412 | rb_ary_push(r_array, rb_str_new2("World!")); 413 | VALUE r_greeting = rb_ary_join(r_array, rb_str_new2(", ")); 414 | # => "Hello, World!" 415 | 416 | ### rb_ary_reverse(`ruby_array`) 417 | 418 | Reverts the order of the array `ruby_array`. 419 | 420 | VALUE r_array = rb_ary_new2(2); 421 | rb_ary_push(r_array, rb_str_new2("Hello")); 422 | rb_ary_push(r_array, rb_str_new2("World!")); 423 | 424 | VALUE r_array_copy = rb_ary_reverse(r_array); 425 | // => ["World!", "Hello"] 426 | 427 | ### rb_ary_to_ary(`ruby_object`) 428 | 429 | Same as calling `Array()` in Ruby. 430 | 431 | VALUE r_value = INT2NUM(42); 432 | VALUE r_array = rb_ary_to_ary(r_value); 433 | // => [42] 434 | 435 | ## Hashes 436 | 437 | ### rb_hash_new() 438 | 439 | Creates a new Ruby Hash 440 | 441 | VALUE r_hash = rb_hash_new(); 442 | // => {} 443 | 444 | ### rb_hash_aset(`ruby_hash`, `key`, `value`) 445 | 446 | Sets the `key` as `value` in the hash `ruby_hash`. All of the 3 parameters have to be Ruby objects. 447 | 448 | VALUE r_hash = rb_hash_new(); 449 | rb_hash_aset(r_hash, rb_str_new2("universal_answer"), INT2NUM(42)); 450 | // => {"universal_answer" => 42} 451 | 452 | ### rb_hash_aref(`ruby_hash`, `key`) 453 | 454 | Gets the value under `key` in the hash `ruby_hash`. Both parameters have to be Ruby objects. 455 | 456 | VALUE r_hash = rb_hash_new(); 457 | rb_hash_aset(r_hash, rb_str_new2("universal_answer"), INT2NUM(42)); 458 | 459 | VALUE r_universal_answer = rb_hash_aref(r_hash, rb_str_new2("universal_answer")); 460 | // => 42 461 | 462 | ## Blocks 463 | 464 | ### rb_block_proc() 465 | 466 | Returns the proc that was given to the method. 467 | 468 | if(rb_block_given_p()) { 469 | VALUE r_proc = rb_block_proc(); 470 | } 471 | 472 | ### rb_block_given_p() 473 | 474 | Returns 1 if a block was given to the method. Otherwise, returns 0. 475 | 476 | if(rb_block_given_p()) { 477 | VALUE r_proc = rb_block_proc(); 478 | } 479 | 480 | ### rb_yield(`ruby_object`) 481 | 482 | Yields `ruby_object`. 483 | 484 | if(rb_block_given_p()) { 485 | VALUE r_val = INT2NUM(42); 486 | r_yield(r_val); 487 | } 488 | 489 | ### rb_yield_values(`ruby_object`, `ruby_object`, ...) 490 | 491 | Yields the values. 492 | 493 | if(rb_block_given_p()) { 494 | r_yield_values(INT2NUM(42), DBL2NUM(3.1415)); 495 | } 496 | --------------------------------------------------------------------------------