Computer >> 컴퓨터 >  >> 프로그래밍 >> Ruby

Ruby C 확장의 인수 구문 분석 마스터하기:단계별 가이드

Ruby는 인간을 먼저, 기계를 위해 만들어진 훌륭한 언어입니다. 읽고 쓰기가 쉽습니다. 무엇이든 작성하는 방법은 다양하며 자신이 선택한 방법의 이름을 입력하여 표준 라이브러리를 추측할 수 있는 경우가 많습니다.

이 때문에 Ruby의 인수는 매우 유연하여 API를 매우 명확하게 표현할 수 있습니다. 그러나 여기에는 단점이 있습니다. Ruby는 Cextension 개발자가 구문 분석하기가 매우 어렵습니다!

이 글에서는 C로 작성된 복잡한 Ruby API를 설정하는 두 가지 방법을 살펴보겠습니다.

  • rb_define_method와 함께 rb_scan_args으로 구문 분석합니다.
  • Ruby 인터페이스 사용

시작해 보세요!

C와 Ruby:소개

앞서 언급했듯이 Ruby는 C 확장 개발자가 구문 분석하기 어렵습니다.

예:

 

Ruby가 작성된 언어인 C의 아름다움은 함수 매개변수를 포함한 단순성에서 비롯됩니다.

  • <data-type> <variable-identifier>
  • ... 가변 인수의 경우.

이는 이해하기 어렵지 않은 코드베이스를 유지하는 데 도움이 될 것입니다.

C 함수를 정의하는 가장 복잡한 방법은 다음과 같습니다.

 

Ruby 코드베이스에 대한 C 확장을 코딩하면 복잡성이 어디서 시작되는지 이해하기 시작할 것입니다. 하지만 걱정하지 마세요. Ruby MRI 개발자가 도와드리겠습니다.

Ruby C 확장의 간단한 메소드 정의

어느 시점에 사용해야 할 메서드인 rb_define_method부터 시작하겠습니다. .

이 저장소에 있는 코드 예제를 따라해 볼 수도 있습니다.

여기는 rb_define_method입니다 님의 서명:

 

그리고 Ruby의 Extension.rdoc에 따르면:

argc는 인수의 개수입니다. argc가 -1이면 함수는 argc, argv 및 self라는 3개의 인수를 받습니다. argc가 -2이면 함수는 self와 args라는 2개의 인수를 받습니다. 여기서 args는 메서드 인수의 Ruby 배열입니다.

간단히 말해서:

 

따라서 API가 고정된 매개변수 길이를 갖는 메소드로만 구성되거나 하나의 가변 매개변수(def foo(*bar))로만 구성된 경우 ), 더 이상 읽지 마세요. 끝났습니다! API를 더욱 다양하게 호출하려면 제 손님이 되어주세요.

그런데 rb_define_method에 대한 더 많은 관련 예제를 원하시면 , 메소드 정의에 대한 Peter Zhu의 기사를 읽어 보시기 바랍니다.

Ruby C API 내부 사용

이제 사용 사례인 복잡한 인수 구문 분석으로 돌아가 보겠습니다. 다행히 일부 도구가 도움이 될 수 있습니다.

하지만 먼저 rb_define_method만 사용하는 경우의 제한 사항을 살펴보겠습니다. .

rb_define_method의 단점

블록 인수에 대한 언급 없음

한 가지 제한 사항은 rb_define_method입니다. 블록 인수를 언급하지 않습니다. 블록을 통과하더라도 Ruby에서는 실제로 중요하지 않기 때문에 고려되지 않습니다. rb_block_given_p을 사용하여 블록이 전달되었는지 확인할 수 있습니다. 또는 rb_need_block . Peter Zhu의 기사에 해당 주제에 대한 자세한 내용이 있습니다.

인수는 다양할 수 있음

또 다른 중요한 제한 사항은 args가 다양할 수 있지만 메서드 호출 자체는 그렇게 제한되지 않는다는 것입니다. 따라서 API를 def foo(bar, *baz)와 같이 만들고 싶다면 , 인수를 구문 분석해야 합니다. 그 길을 따라가는 데 도움이 되는 몇 가지 방법이 있습니다. rb_check_arity rb_define_method의 -1 버전과 함께 사용할 수 있는 버전입니다. .

함수 서명은 다음과 같습니다:

 

키워드 인수

우리가 겪게 될 마지막 제한 사항 중 하나는 키워드 인수를 사용하는 것입니다. 그리고 이것이 이 글의 핵심이 될 것이므로 최선을 다해 유지했습니다.

키워드 인수를 올바르게 구문 분석하려면 먼저 키워드 인수를 검색해야 합니다. 다행히 Ruby C API에는 이를 위한 메서드인 rb_scan_args가 함께 제공됩니다. .

rb_scan_args는 다음과 같습니다. 서명:

 

rb_scan_args를 통과했습니다. argcargv rb_define_method에서 제공 — 인수를 구문 분석하는 방법을 알려주는 문자열(fmt ) 및 해당 인수에 대한 수신자입니다. 자, Ruby의 모든 인수 복잡성이 한 줄로 구문 분석되었습니다! 거의 그렇죠.

fmt 방법에 대한 공식 표현은 Extension.rdoc를 참조할 수 있습니다. 아래 예에서 부분적으로 다루겠지만 작성해야 합니다.

함수 작성 및 구문 분석:예

이 기사의 나머지 부분에서는 다음 함수를 작성한다고 가정해 보겠습니다.

 

rb_scan_args를 사용하여 이를 구문 분석합니다. 다음과 같이 보일 것입니다:

 

"1*:" 횡설수설은 다음을 의미합니다:

  • 1 :하나의 필수 위치 인수
  • * :위치 인수가 필요하지 않습니다.
  • : :끝에 키워드 인수

키워드 인수 구문 분석

이제 우리는 방법을 제한했지만 불행하게도 아직 끝나지 않았습니다. 현재 API는 def voronoi_diagram(envelope, *polygons, **kwargs)입니다. .

마지막으로 rb_get_kwargs를 사용하여 해당 키워드 인수를 구문 분석해야 합니다. .

 

필수 및 선택적 인수를 선택해야 합니다. 완료되면 table를 사용합니다. Ruby에게 해당 인수의 이름을 알려주고 결과를 배열(values)에 저장합니다. ).

 

거기 있어요! C만을 사용하여 구문 분석되는 복잡한 Ruby 메소드입니다. 그러나 이것이 너무 복잡하다면 다른 옵션이 있습니다.

Ruby 인터페이스 사용

문제를 처리하는 또 다른 방법은 실제로 Ruby의 구문을 직접 사용하고 Ruby 단계에서 구문 분석을 수행하는 것입니다.

 

이를 통해 rb_define_method의 세 번째 형식을 직접 사용할 수 있습니다. , 다음과 같은 C 메소드의 경우:

 

그러면 거기까지입니다. Ruby 구현의 일부 메서드에 실제로 사용되는 우아한 솔루션(Primitive 사용)으로 문제를 완전히 피할 수 있습니다. 수업).

MRI에서 사용하는 클래스는 상당히 복잡하고 C 자체를 생성하지만 여기서 영감을 얻을 수 있습니다.

c_voronoi_diagram가 표시되지 않도록 개체를 만들고 메서드를 연결해 보겠습니다. API 사용자의 경우:

 
 

RGeo의 코드베이스에서 이 클래스의 실제 사용 사례를 확인하세요.

인수 구문 분석:어떤 방법을 사용해야 합니까?

이 저장소는 C로 작성된 복잡한 Ruby API를 설정하는 두 가지 방법을 보여줍니다. 요약하자면:

  • rb_define_method 사용 rb_scan_args으로 구문 분석합니다.
  • Ruby 인터페이스 사용

성능 측면에서 두 솔루션을 비교할 때 거의 동일합니다(Ruby 구문 분석은 내 M1에서 평균 1.02배 빠릅니다). 별 차이가 없습니다.

RGeo lib에서 우리의 첫 번째 디자인 선택은 가변 길이 인수만 사용하는 API를 갖는 것이었습니다. 키워드도 없고 블록도 없습니다. 이는 매우 제한적일 수 있으며 현재 Primitive를 사용하고 있습니다. 더 복잡한 논쟁을 허용하는 방법입니다.

Ruby 인터페이스 사용의 이점

내 조언은 다음을 포함하여 여러 가지 이유로 Ruby 인터페이스를 사용하라는 것입니다.

  • 코드 크기가 더 작습니다
  • 변경이 더 쉬워졌습니다

전반적으로 이는 코드베이스를 읽는 경험을 더 단순하게 만듭니다.

Ruby 사용자가 자신이 사용하는 gem의 소스 코드를 읽도록 유도하는 것은 나에게 중요합니다. Ruby는 읽기 쉽습니다 , 보석도 마찬가지입니다.

rb_define_method 사용의 이점

그러나 C 버전에서는 매우 유용한 내부 메서드를 맛볼 수 있습니다. 예를 들어 rb_check_arity 여전히 정말 유용합니다. 블록을 처리하는 방법도 훌륭하며 블록에 Ruby 파사드를 사용할 필요가 없을 수도 있습니다.

귀하의 사용 사례에 가장 적합한 선택을 찾는 것이 중요합니다.

마무리

이 게시물에서는 rb_define_method을 사용하여 Ruby C 확장에서 인수를 구문 분석하는 두 가지 방법을 살펴보았습니다. (제한 사항도 간략하게 살펴보고) rb_scan_args으로 구문 분석합니다. 그리고 Ruby 인터페이스를 사용합니다.

C 확장에 대해 더 자세히 알고 싶다면 다음을 추천합니다:

  • 처음부터 Ruby C 확장 구축
  • C면을 따라 걷는 루비스트의 산책
  • Mac에서 Ruby C 확장 프로그램 작업

그리고 제가 드리고 싶은 마지막 조언은 RGeo를 확인해 보세요. 활발한 개발에서 널리 사용되는 C 확장 코드베이스입니다. 내 예시의 대부분은 여기에서 나왔습니다.

즐거운 코딩 되세요!

추신 Ruby Magic 게시물이 보도되는 즉시 읽으려면 Ruby Magic 뉴스레터를 구독하고 단 하나의 게시물도 놓치지 마세요!

Ruby C 확장의 인수 구문 분석 마스터하기:단계별 가이드

율리스 부오노모

우리의 객원 저자인 Ulysse는 대부분의 시간을 전 세계를 여행하는 데 바치는 전직 Ruby 개발자입니다. 그는 여가 시간을 RGeo와 Ruby에 전념하며 Ruby의 내부를 만지는 것을 좋아합니다.

Ulysse Buonomo의 모든 기사