2009-03-09 31 views
18

Tôi hy vọng sẽ sử dụng Ruby làm ngôn ngữ kịch bản cho công cụ trò chơi của tôi. Tôi đã tìm thấy các bài viết thông thường mô tả cách gọi các lớp Ruby từ mã C++ và ngược lại (ví dụ: here) nhưng tôi không thể thấy rõ cách làm những gì tôi muốn theo cách đó ...Nhúng trình thông dịch Ruby vào ứng dụng C++

Động cơ của tôi hiện đang sử dụng một ngôn ngữ nhỏ tôi đã viết bản thân mình với Flex và Bison, và một ngăn xếp dựa trên máy ảo nhỏ. Các tập lệnh không phải lúc nào cũng chạy ngay từ đầu đến cuối, ví dụ đôi khi chúng bao gồm các lệnh như "ngủ trong 2 giây" hoặc "đợi cho đến khi ký tự kết thúc", vì vậy trình lập lịch sẽ theo dõi trạng thái của mỗi tập lệnh và hướng dẫn con trỏ và biết thời điểm tiếp tục chúng, v.v. Vì vậy, có vẻ như tôi thực sự cần một loại thông dịch viên Ruby nhúng mà tôi có thể thực hiện một mức độ kiểm soát nhất định, thay vì chỉ đơn giản gọi các phương thức Ruby. Hay tôi chỉ là ngớ ngẩn và thiếu cái gì đó?

Tôi đang làm việc trong Microsoft Visual C++, vì vậy, lý tưởng là mọi giải pháp sẽ biên dịch tốt đẹp và dễ dàng trong đó.

Trả lời

4

Bạn đang đi đúng hướng. Điều quan trọng là làm điều gì đó tương tự như phần trên Embedding Concepts trong liên kết bạn đã đăng. Trong thuật ngữ đơn giản nó là ít hơn:

ruby_init(); 
ruby_script("some_script"); 

Bạn có thể cần phải sao chép tất cả những thứ #ifdef từ main.c để có được tất cả mọi thứ làm việc. Từ đó nó là vấn đề xây dựng một API cho các hàm C++ của bạn mà bạn muốn trưng ra, và tùy thuộc vào thiết kế của bạn, đa luồng điều.

+0

Điều này dường như không giải quyết được câu hỏi về cách bạn nhận một trong những tập lệnh đó đi vào chế độ ngủ, ví dụ - mặt lập lịch biểu của sự vật. – andygeers

4

Bạn luôn có thể thiết kế lại cách các tập lệnh hoạt động cho phù hợp với công cụ tập lệnh thay vì cố gắng làm cho động cơ hoạt động với các mẫu kịch bản gốc.

Vì vậy, nếu bạn có điều này:

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

mà sẽ yêu cầu kịch bản bị đình chỉ trên dòng ngủ, làm như sau:

proc 
    action1 
    action2 
    set timer (time, callback_proc) 
end 

callback_proc 
    action3 
end 

cho phép kết thúc đoạn mã script mỗi phương pháp gọn gàng . Nó sẽ không cần nhiều thay đổi đối với phía lưu trữ - mỗi phiên bản yêu cầu một số dạng hệ thống sự kiện có thể khởi động lại công cụ kịch bản.

3

guide về cách nhúng ruby ​​vào ứng dụng C++. Điều đó có thể hữu ích. Nếu không, hãy truy cập Ruby documentation. Bài viết Embed Ruby in C cũng có thể hữu ích.

+2

Đối với người đọc trong tương lai, trang web có hướng dẫn C++ đã được tổ chức lại. Url mới là: http://aeditor.rubyforge.org/ruby_cplusplus/index.html – Iain

+3

Thật không may cả giả mạo và opera của tôi đã bị đóng, do đó không có hướng dẫn hoặc bài viết nào vẫn có sẵn. –

0

Tôi nghĩ điều bạn muốn làm là sử dụng các chuỗi của Ruby. Tôi đã thực hiện một chút công bằng của đào thông qua các đoạn mã Ruby và tôi biết rằng (nơi pthreads có sẵn) ngủ được thực hiện trong một thời trang không chặn bằng cách sử dụng pthread_cond_timedwait. Điều này unblocks các thông dịch viên để các chủ đề khác có thể tiếp tục thực hiện.

Mã của riêng bạn sẽ phải tôn trọng chủ đề của Ruby khi nói đến tương tác với trình thông dịch Ruby. Họ vẫn có một Global VM Lock trong Ruby, điều đó có nghĩa là bạn nên cẩn thận khi sửa đổi bất cứ thứ gì trong trình thông dịch mà không cần phải tự khóa.

28

Dưới đây là ví dụ bao gồm xử lý lỗi.

#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

cảm ơn bạn, câu trả lời hay nhất ở đây :) – Cynede

+1

Đó là một câu trả lời một phần, nhưng theo như tôi có thể nói điều này vẫn không tham gia với câu hỏi về các tập lệnh bị treo? – andygeers

Các vấn đề liên quan