embedding ruby

Discussion in 'Ruby' started by Josep Pujol, Feb 4, 2010.

  1. Josep Pujol

    Josep Pujol Guest

    Hello,

    After reading a little, I found out that ruby was not designed with
    embedding in mind. However, I really love Ruby and I would like to embed
    it into my application.

    I would like to know if the problem with embedding ruby is that there
    are global variables and also because of the stack.

    If this is the case, can I assume that it is safe to use the ruby engine
    if I initialize it in the main process, before any thread is launched in
    my C++ application (so the stack is in the lower position) and I use
    mutex to prevent more than one run at any time (for the global
    variables)?

    Thank you very much in advance.
    Josep.
    --
    Posted via http://www.ruby-forum.com/.
     
    Josep Pujol, Feb 4, 2010
    #1
    1. Advertising

  2. Josep Pujol

    Bill Kelly Guest

    Josep Pujol wrote:
    >
    > I would like to know if the problem with embedding ruby is that there
    > are global variables and also because of the stack.
    >
    > If this is the case, can I assume that it is safe to use the ruby engine
    > if I initialize it in the main process, before any thread is launched in
    > my C++ application (so the stack is in the lower position) and I use
    > mutex to prevent more than one run at any time (for the global
    > variables)?


    We embed ruby 1.8.x in a C++ app on Windows / OS X.

    In our case, we run Ruby in a separate thread. Only trick was that
    the stack size of threads other than the main thread may be small by
    default. And we use boost threads. So I had to modify boost to
    create the thread with a large enough stack:

    // boost/libs/thread/src/thread/cpp
    #if defined(BOOST_HAS_PTHREADS)
    const size_t THREAD_STACK_SIZE_BYTES = 8 * 1024 * 1024;
    pthread_attr_t tattr;
    int res = 0;
    res = pthread_attr_init(&tattr);
    if (res != 0)
    throw thread_resource_error();
    res = pthread_attr_setstacksize(&tattr, THREAD_STACK_SIZE_BYTES);
    if (res != 0)
    throw thread_resource_error();
    res = pthread_create(&m_thread, &tattr, &thread_proxy, &param);
    (void) pthread_attr_destroy(&tattr);
    if (res != 0)
    throw thread_resource_error();



    When Ruby code wants to call into the C++ side of the app, it's easy,
    we just wrap whatever functionality from the app in a Ruby class, as
    one would do with any ruby 'C' extension.

    In the other direction, when an arbitrary C++ thread wants to talk to
    Ruby, it's a little more complicated.

    I've set up a queueing approach, where a C++ thread can create a
    "RubyContext" object, and throw eval's at it. Like:


    RubyContext r;

    std::string result = r.eval("...some_ruby_code...");


    It works out pretty well.

    I haven't tried embedding ruby 1.9.x yet.


    Regards,

    Bill
     
    Bill Kelly, Feb 5, 2010
    #2
    1. Advertising

  3. Josep Pujol wrote:
    > After reading a little, I found out that ruby was not designed with
    > embedding in mind. However, I really love Ruby and I would like to embed
    > it into my application.


    It is true that Ruby wasn't designed with embedding in mind. However,
    this ...

    > I would like to know if the problem with embedding ruby is that there
    > are global variables and also because of the stack.


    .... has absolutely nothing to do with that. What you are asking about
    has nothing to do with Ruby, this kind of behavior is specific to the
    particular implementation you are using.

    Rubinius was very much designed for embedding. It doesn't have any
    global variables or other sort of global state and it minimizes its
    use of the C stack as far as possible. It also has a well-defined
    embedding API. (In earlier versions, it didn't use the C stack *at
    all*, but that was changed for performance and interoperability
    reasons.)

    JRuby also is easy to embed, and it also has a well-defined embedding
    API. It supports the scripting API which is part of the Java Platform
    Specification, and also its own scripting API (RedBridge).

    IronRuby supports the standard DLR embedding API and can be easily
    embedded.

    If you look at the actual commandline interpreter binaries for JRuby
    and IronRuby, you will find that they are just pretty simple
    commandline wrappers around the engines, using the respective
    embedding APIs.

    Personally, I would look at Rubinius, JRuby or IronRuby for embedding,
    rather than MRI or YARV. But really, I would look at Lua, because
    while you can find a Ruby *implementation* that is specifically
    designed for embedding, this doesn't change the fact that the Ruby
    *language* isn't.

    jwm
     
    Jörg W Mittag, Feb 5, 2010
    #3
  4. Josep Pujol

    Josep Pujol Guest

    Thanks for your answer.

    Jörg W Mittag wrote:
    > Personally, I would look at Rubinius, JRuby or IronRuby for embedding,
    > rather than MRI or YARV. But really, I would look at Lua, because
    > while you can find a Ruby *implementation* that is specifically
    > designed for embedding, this doesn't change the fact that the Ruby
    > *language* isn't.
    >
    > jwm


    I've just downloaded the rubinius code and I read this statement in the
    README file.

    5. Goals

    * Thread safety. Rubinius intends to be thread-safe so you could embed
    more
    than one interpreter in a single application. It does not currently
    meet
    this goal due to some components borrowed from the mainline Ruby
    interpreter.

    Is this true also for the 1.0 version? (or this is an old statement that
    hasn't been removed)

    About Lua, I've seen it, but my blind love about ruby is too strong...
    ;-)

    By the way, I've ruled out JRuby and IronRuby because they need extra
    components (java and mono).
    --
    Posted via http://www.ruby-forum.com/.
     
    Josep Pujol, Feb 6, 2010
    #4
  5. Jörg W Mittag wrote:
    > [...] But really, I would look at Lua, because
    > while you can find a Ruby *implementation* that is specifically
    > designed for embedding, this doesn't change the fact that the Ruby
    > *language* isn't.


    What do you mean? What is there in the language itself that hinders
    embedding?
    --
    Posted via http://www.ruby-forum.com/.
     
    Albert Schlef, Feb 7, 2010
    #5
  6. Josep Pujol

    Bill Kelly Guest

    Josep Pujol wrote:
    >
    > Bill Kelly wrote:
    >> We embed ruby 1.8.x in a C++ app on Windows / OS X.
    >>
    >> In our case, we run Ruby in a separate thread. Only trick was that
    >> the stack size of threads other than the main thread may be small by
    >> default. And we use boost threads. So I had to modify boost to
    >> create the thread with a large enough stack:

    >
    > I plan to use ruby in several threads (it's a gui application and
    > each menu can trigger some ruby code). Is it safe enough to use
    > a mutex or I must initialize something (the stack?) for each
    > thread?


    Well again, my experience is only embedding MRI Ruby 1.8.x. In this
    case, the ruby interpreter itself runs in a single thread.

    So on the Ruby side, all Ruby-threads are green threads running in
    the single native Ruby thread.

    We do indeed use Ruby threads to create GUI elements. And in the
    reverse direction we do forward GUI events from the C++ GUI event
    thread back to Ruby.

    What we never do is allow arbitrary C++ threads to call directly
    into Ruby.

    So in a situation where C++ makes a call like this:

    ruby_context.eval("GUI.forward_event:)click,"+control_id+")");

    This 'eval' doesn't call ruby directly, but queues the command and
    waits for the Ruby native thread to process the command.

    So there is indeed a mutex (and a condition variable) involved here,
    but its purpose is to implement the queuing mechanism between C++
    threads and the Ruby interpreter thread.



    For what it's worth, in the latest app I'm developing, I've changed
    this so that Ruby runs in an entirely separate process. And the C++
    part of th app just acts like a "window server", which the Ruby
    process connects to, and uses to create the GUI.


    Regards,

    Bill
     
    Bill Kelly, Feb 7, 2010
    #6
  7. Josep Pujol

    Seebs Guest

    On 2010-02-07, Albert Schlef <> wrote:
    > Jörg W Mittag wrote:
    >> [...] But really, I would look at Lua, because
    >> while you can find a Ruby *implementation* that is specifically
    >> designed for embedding, this doesn't change the fact that the Ruby
    >> *language* isn't.


    > What do you mean? What is there in the language itself that hinders
    > embedding?


    It's not so much that it "hinders" embedding is that embedding isn't the
    explicit design goal. Lua is *designed* with the intent that the primary
    use would be embedding it in other programs.

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
     
    Seebs, Feb 8, 2010
    #7
  8. Josep Pujol wrote:
    > Thanks for your answer.
    >
    > Jörg W Mittag wrote:
    >> Personally, I would look at Rubinius, JRuby or IronRuby for embedding,
    >> rather than MRI or YARV. But really, I would look at Lua, because
    >> while you can find a Ruby *implementation* that is specifically
    >> designed for embedding, this doesn't change the fact that the Ruby
    >> *language* isn't.

    > I've just downloaded the rubinius code and I read this statement in the
    > README file.
    >
    > 5. Goals
    >
    > * Thread safety. Rubinius intends to be thread-safe so you could embed
    > more than one interpreter in a single application. It does not currently
    > meet this goal due to some components borrowed from the mainline Ruby
    > interpreter.
    >
    > Is this true also for the 1.0 version? (or this is an old statement that
    > hasn't been removed)


    I'm not sure. I haven't followed Rubinius recently, and pretty much
    *everything* has changed since I last followed it closely: a new VM,
    three new parsers, a new compiler, a new garbage collector, a new
    threading model. Literally *nothing* is like when I last looked at it.

    However, please note that this snippet only talks about embedding
    *multiple* Rubinius interpreters into a *single process*. Also, it
    specifically mentions that the problematic parts are borrowed from
    MRI/YARV, which means that if you use one of those, you will have to
    deal with the exact same problems.

    jwm
     
    Jörg W Mittag, Feb 13, 2010
    #8
  9. Albert Schlef wrote:
    > Jörg W Mittag wrote:
    >> [...] But really, I would look at Lua, because
    >> while you can find a Ruby *implementation* that is specifically
    >> designed for embedding, this doesn't change the fact that the Ruby
    >> *language* isn't.

    > What do you mean? What is there in the language itself that hinders
    > embedding?


    Everything that you don't need.

    That's kind of a dick answer. What I mean by that is that when you
    embed a language into an application, this is usually a very special
    purpose deal. Which means that all the stuff which makes Ruby
    *brilliant* as a general purpose language, can get in the way. Do you
    really need an almost Turing-complete Regexp implementation in a CAD
    program? Or text processing? Do you need Database I/O in a game AI?
    Arbitrary precision integers in a text editor?

    Lua is often criticized for its small (to almost non-existent)
    standard library (compared to Python, Ruby, Java, .NET), but when the
    main purpose is as a special purpose embedded language, then there
    simply isn't that much "standard" functionality that you could put in
    a standard library. What do Adobe Lightroom, World of Warcraft and
    NginX have in common that you could put there?

    Lua is designed in such a way that the embedding program *is* the
    "standard" library (or more specifically *provides* the library). Ruby
    comes with "batteries included" which is really great if you want to
    run it autonomous, but is just annoying when you want to hook it up to
    your application's power supply.

    jwm
     
    Jörg W Mittag, Feb 13, 2010
    #9
  10. On Feb 12, 2010, at 4:05 PM, J=F6rg W Mittag wrote:

    > Josep Pujol wrote:
    >> Thanks for your answer.
    >>=20
    >> J=F6rg W Mittag wrote:
    >>> Personally, I would look at Rubinius, JRuby or IronRuby for =

    embedding,
    >>> rather than MRI or YARV. But really, I would look at Lua, because
    >>> while you can find a Ruby *implementation* that is specifically
    >>> designed for embedding, this doesn't change the fact that the Ruby
    >>> *language* isn't.

    >> I've just downloaded the rubinius code and I read this statement in =

    the=20
    >> README file.
    >>=20
    >> 5. Goals
    >>=20
    >> * Thread safety. Rubinius intends to be thread-safe so you could =

    embed=20
    >> more than one interpreter in a single application. It does not =

    currently=20
    >> meet this goal due to some components borrowed from the mainline =

    Ruby=20
    >> interpreter.
    >>=20
    >> Is this true also for the 1.0 version? (or this is an old statement =

    that=20
    >> hasn't been removed)

    >=20
    > I'm not sure. I haven't followed Rubinius recently, and pretty much
    > *everything* has changed since I last followed it closely: a new VM,
    > three new parsers, a new compiler, a new garbage collector, a new
    > threading model. Literally *nothing* is like when I last looked at it.
    >=20
    > However, please note that this snippet only talks about embedding
    > *multiple* Rubinius interpreters into a *single process*. Also, it
    > specifically mentions that the problematic parts are borrowed from
    > MRI/YARV, which means that if you use one of those, you will have to
    > deal with the exact same problems.




    You can currently run multiple rubinius VM's in one process, =
    each VM will run on it's own native thread in parallel and there is a =
    simple message passing interface to pass messages between running VM's.

    Cheers-
    Ezra Zygmuntowicz
     
    Ezra Zygmuntowicz, Feb 13, 2010
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Brian Candler

    Embedding ruby - name clashes

    Brian Candler, Jul 22, 2003, in forum: Ruby
    Replies:
    0
    Views:
    97
    Brian Candler
    Jul 22, 2003
  2. Basile STARYNKEVITCH

    embedding ruby - some questions

    Basile STARYNKEVITCH, Aug 31, 2003, in forum: Ruby
    Replies:
    0
    Views:
    124
    Basile STARYNKEVITCH
    Aug 31, 2003
  3. Basile STARYNKEVITCH

    questions about embedding ruby

    Basile STARYNKEVITCH, Sep 1, 2003, in forum: Ruby
    Replies:
    3
    Views:
    138
  4. Basile STARYNKEVITCH
    Replies:
    0
    Views:
    108
    Basile STARYNKEVITCH
    Sep 2, 2003
  5. Charles Comstock
    Replies:
    1
    Views:
    121
    Lyle Johnson
    Jun 25, 2004
Loading...

Share This Page