C 확장을 작성하면 C에서 Ruby와 상호 작용할 수 있습니다.
C의 속도로 최적화하려는 특정 중요한 방법이 있거나 C 라이브러리와 Ruby 간의 인터페이스를 생성하려는 경우 이 작업을 수행할 수 있습니다.
대안은 FFI 모듈을 사용하는 것입니다.
지금 :
C 확장자를 작성하는 방법을 알아봅시다!
첫 번째 C 확장
extconf.rb
라는 파일을 만듭니다. 다음 콘텐츠:
require 'mkmf' create_header create_makefile 'foobar'
그런 다음 ruby extconf.rb
를 실행합니다. 그러면 몇 개의 파일이 생성됩니다(Makefile
&extconf.h
). 이 파일을 변경하지 마십시오.
이제 foobar.c
를 만듭니다. , 이 이름은 create_makefile
에서 가져옵니다. extconf.rb
줄 . 원하는 경우 변경할 수 있지만 .c
와 일치해야 합니다. 이 작업을 위한 파일 이름입니다.
foobar.c
내부 당신은 이것을 추가합니다:
#include "ruby.h" #include "extconf.h" void Init_foobar() { // Your C code goes here }
이것은 C 확장의 기본 골격입니다. extconf.rb
에 선언한 이름을 사용해야 합니다. 플러스 단어 Init_
. 이 경우 Init_foobar
.
make
를 실행하여 컴파일할 수 있습니다. , 그리고 당신이 얻는 것은 so
require
를 사용하여 Ruby 애플리케이션에 로드할 수 있는 파일 .
C에서 루비 메소드 작성
Ruby 코드에서 호출할 수 있는 c 함수를 만들 수 있습니다. 이것이 내장 클래스와 메소드가 작동하는 방식입니다.
모든 Ruby 메서드는 VALUE
를 반환해야 합니다. . VALUE
Ruby 개체입니다.
예 :
VALUE rb_return_nil() { return Qnil; }
이제 이 함수를 Ruby 클래스나 모듈에 연결해야 합니다. 새 클래스를 만들거나 기존 클래스를 사용할 수 있습니다.
여기서 모듈을 만들고 있습니다 :
void Init_foobar() { VALUE mod = rb_define_module("RubyGuides"); rb_define_method(mod, "return_nil", rb_return_nil, 0); }
rb_define_method
를 사용할 수 있습니다. 이 모듈에 C 함수를 연결하는 메서드입니다.
인수 :
인수 | 설명 |
---|---|
모드 | 모듈 개체 |
"print_hello" | 루비 메서드 이름 |
rb_print_hello | C 함수의 이름 |
0 | 이 메서드가 사용하는 인수의 수, 가변 인수에 -1 사용 |
이제 make
를 실행하세요. 확장을 다시 컴파일하고 다음과 같이 시도하십시오.
require 'foobar' include RubyGuides print_hello
자, 방금 Ruby에서 C 함수를 호출했습니다!
C에서 루비 해시 만들기
종종 C에서 Ruby 객체를 만들고 조작하고 싶을 것입니다.
C API를 사용하여 그렇게 할 수 있습니다.
예를 들어 해시를 만들고 여기에 일부 요소를 추가하려면:
VALUE create_hash() { hash = rb_hash_new(); rb_hash_aset(hash, rb_str_new2("test"), INT2FIX(1)); return hash; }
여기서 주목해야 할 두 가지 중요한 사항은 먼저 rb_str_new2
입니다. 함수를 사용하면 Ruby 문자열이 생성됩니다.
그런 다음 INT2FIX
매크로, 이것은 일반 정수를 루비 정수로 변환합니다.
이제 rb_define_method
를 사용하여 이 함수를 Ruby에 노출하면 하나의 키(test
) 및 1
값 .
변경할 때마다 확장 프로그램을 다시 컴파일하는 것을 잊지 마세요 🙂
문자열 작업
C 함수도 매개변수를 사용할 수 있습니다.
예:
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); }
여기에서 VALUE
를 사용합니다. (ruby 객체)를 인수로 사용하고 RB_TYPE_P
가 있는 문자열인지 확인합니다. 매크로. 그런 다음 RSTRING_LEN
을 사용하여 문자열 길이를 인쇄합니다. 매크로.
문자열 데이터에 대한 포인터를 원하면 RSTRING_PTR
를 사용할 수 있습니다. 매크로.
예 :
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; }
또한 self
에 또 다른 매개변수가 있음을 확인하세요. , 메소드 호출을 받는 객체입니다.
String 클래스 자체에서 이 메서드를 정의하려면 다음과 같이 하면 됩니다.
void Init_foobar() { rb_define_method(rb_cString, "print_length", rb_print_length, 0); }
요약
Ruby 프로그램에서 C의 모든 기능에 액세스할 수 있도록 Ruby용 C 확장을 작성하는 방법을 배웠습니다. 또한 C 함수를 Ruby에 노출하는 방법과 문자열 및 해시와 같은 C의 Ruby 객체로 작업하는 방법도 배웠습니다.
C에서 Ruby와 상호 작용하기 위해 더 많은 기능이 필요한 경우 문서화가 잘 되어 있지 않기 때문에 Ruby의 소스 코드 및 C 확장 코드에서 해당 기능을 찾아야 할 수도 있습니다.
이 기사가 유용하고 흥미로웠기를 바랍니다! 그렇다면 친구들과 공유하여 그들도 즐길 수 있도록 하십시오.