2009-03-09 3 views
18

내 게임 엔진의 스크립팅 언어로 Ruby를 사용하고 싶습니다. Ruby 클래스를 C++ 코드에서 호출하는 방법을 설명하는 일반적인 기사 (예 : here)를 찾았으나 원하는 작업을 수행하는 방법을 볼 수 없습니다.C++ 응용 프로그램에 Ruby 인터프리터 포함하기

내 엔진 현재 Flex와 Bison으로 작성한 작은 언어와 작은 스택 기반 가상 시스템을 사용합니다. 스크립트는 항상 처음부터 끝까지 올바르게 실행되는 것은 아닙니다. 예를 들어 "2 초 동안 대기"또는 "캐릭터가 워킹을 마칠 때까지 기다리기"와 같은 명령을 포함하기 때문에 스케줄러는 각 스크립트 및 명령의 상태를 계속 모니터링합니다 포인터를 인식하고 언제 다시 시작할 것인지 등을 알고 있습니다.

그래서 Ruby 메서드를 호출하기보다는 특정 수준의 제어를 수행 할 수있는 임베디드 루비 인터프리터가 필요합니다. 아니면 그냥 무언가를 놓치고 있습니까?

저는 Microsoft Visual C++에서 작업하고 있으므로 이상적으로 모든 솔루션이 훌륭하고 쉽게 컴파일 될 것입니다.

답변

4

당신은 올바른 길을 가고 있습니다. 열쇠는 게시 한 링크의 Embedding Concepts 섹션과 유사한 작업을 수행하는 것입니다. 간단히 말해서 그건 좀 이상 : 당신은 모든 작업을 얻을 수 main.c에서 모든 #ifdef 물건을 복사해야 할 수도 있습니다

ruby_init(); 
ruby_script("some_script"); 

. 그때부터는 노출하고자하는 C++ 함수에 대한 API를 작성해야하며, 디자인에 따라 멀티 스레딩이 필요합니다.

+0

이것은 여전히 ​​스크립트 중 하나를 절전 모드로 전환하는 방법에 대한 문제를 해결하지 못하는 것처럼 보입니다. – andygeers

4

원본 스크립트 패러다임을 사용하여 엔진을 작동시키지 않고 스크립트 엔진에 맞게 스크립트의 작동 방식을 언제든지 다시 디자인 할 수 있습니다. 이 있었다면

그래서 : 스크립트를 필요로

proc: 
    action 1 
    action 2 
    sleep a bit 
    action 3 
end 

가 수면 줄에 일시 정지해야 할를 다음을 수행하십시오 깔끔하게 각 방법을 스크립팅 엔진 마무리를 할 수 있습니다

proc 
    action1 
    action2 
    set timer (time, callback_proc) 
end 

callback_proc 
    action3 
end 

을 . 그것은 호스팅 측에 많은 변화를 필요로하지 않을 것입니다 - 각 버전은 스크립트 엔진을 재시작 할 수있는 어떤 형태의 이벤트 시스템을 필요로합니다.

3

루비를 C++ 응용 프로그램에 임베드하는 방법은 guide입니다. 도움이 될 수 있습니다. 그렇지 않으면 Ruby documentation으로 이동하십시오. Embed Ruby in C 도움말도 도움이 될 수 있습니다.

+2

향후 독자를 위해 C++ 가이드가있는 웹 사이트가 재구성되었습니다. 새로운 URL은 다음과 같습니다. http://aeditor.rubyforge.org/ruby_cplusplus/index.html – Iain

+3

불행히도 루비 포지와 오페라는 모두 폐쇄되었으므로 가이드 나 기사는 아직 사용할 수 없습니다. –

0

Ruby의 스레드를 사용하고 싶다고 생각합니다. 나는 Ruby 쓰레딩 코드를 파고 들었고, pthread가 사용 가능한 곳에서 sleep이 pthread_cond_timedwait을 사용하여 논 블로킹 방식으로 구현된다는 것을 알고있다. 이렇게하면 다른 스레드가 계속 실행될 수 있도록 인터프리터가 차단됩니다.

Ruby 인터프리터와 상호 작용할 때 자신의 코드는 Ruby의 스레드를 존중해야합니다. 그들은 여전히 ​​Ruby에서 Global VM Lock을 가지고 있습니다. 즉, 스스로 잠금을하지 않고도 인터프리터에서 아무 것도 수정하지 않도록 조심해야한다는 의미입니다.

28

다음은 오류 처리를 포함하는 예입니다.

#include <iostream> 
#include <ruby.h> 

using namespace std; 

int main(void) 
{ 
    ruby_init(); 
    ruby_init_loadpath(); 
    int status; 
    rb_load_protect(rb_str_new2("./test.rb"), 0, &status); 
    if (status) { 
    VALUE rbError = rb_funcall(rb_gv_get("$!"), rb_intern("message"), 0); 
    cerr << StringValuePtr(rbError) << endl; 
    }; 
    ruby_finalize(); 
    return status; 
} 
+0

고맙습니다. 여기에 대한 답변이 가장 좋습니다. – Cynede

+1

부분적인 답변이지만, 아직도 내가 말할 수있는 한 정지 된 스크립트의 질문에 개입하지 않습니까? – andygeers

관련 문제