Yes there is. Let me show you the mapping :-)
1) In Lua you have lua_CFunction :
typedef int (*lua_CFunction) (lua_State *L);
it gets arguments on the stack, pushes results on the stack and
returns number of results.
In V8 you have v8::InvocationCallback:
typedef Handle<Value> (*InvocationCallback)(const Arguments& args);
it gets Arguments object which provides access to arguments and returns result.
2) In Lua if you want to create function value from lua_CFunction foo you do
lua_pushcfunction(L, foo);
// function object is now on top of the stack
In V8 to create function from InvocationCallback foo you do:
Local<Function> f = FunctionTemplate::New(foo)->GetFunction();
3) To set global variable bar in Lua you push the value on the stack
and then call
lua_setglobal(L, "bar"); // pop value from the stack and assign it to
global called bar
In V8 you just do:
Context::GetCurrent()->Global()->Set(v8::String::New("bar"), val); //
where val is something you want to assign to global
4) In Lua lua_register(L, name, func) is just
lua_pushcfunction(L, func); // push function on the stack
lua_setglobal(L, name); // pop function from the stack and assign it
to global called name.
This translates to V8 as:
Context::GetCurrent()->Global()->Set(v8::String::New(name),
FunctionTemplate::New(func)->GetFunction());
// Concept of global object in V8/JavaScript is a bit more complicated
than in Lua so instead of using Context::GetCurrent()->Global() you
can access it in a different ways.
--
Vyacheslav Egorov
On Wed, Jan 19, 2011 at 3:58 PM, Jak Sprats <[email protected]> wrote:
> hi
>
> this is a very helpful metaphor, I can read your C-calling-Lua example
> and then get the C-calling-Javascript like i was reading a tutorial,
> thank you.
>
> One question, and this is not about calling C-calling-JS, it is about
> calling JS-calling-C
>
> In AlchemyDB, in C, I have the following line
> lua_register(Lua, "client", luaCall_client);
> Which tells the Lua interpreter, that when a lua scripts makes a
> "client()" call, it should be rerouted to my C function
> "luaCall_client()".
>
> Is there a similarly simple mechanism to register JS functions to call
> defined C functions.
>
> This is the part I am not yet fully grasping on how to code it :)
>
> - Jak
>
> On Jan 18, 8:08 am, Vyacheslav Egorov <[email protected]> wrote:
>> Jak,
>>
>> I think it would be pretty easy to convert your Lua intergration into
>> V8 intergration line by line without relying on any third party
>> libraries.
>>
>> Let me show you a mapping between Lua and V8 APIs
>>
>> Lua:
>> // Lua API manipulates with stack. Anything on the stack will be kept
>> alive when GC happens.
>> int code = luaL_dostring(L, s);
>> if (code) {
>> // error is on top of the stack
>> const char *error_message = lua_tostring(L, -1);
>> report(error_message);} else {
>>
>> // return values are on top of the stack
>>
>> }
>>
>> V8:
>> // V8 does not have implicit stack. Instead API is all about Handles.
>> // Handles keep what they reference alive during GC.
>> // There are two types of the Handles: Local and Persistent.
>> // Each Local handle is owned by a HandleScope --- when HandleScope
>> dies so do all Local handles it owns.
>> // In terms of Lua: creating HandleScope is like remembering height of
>> Lua stack, creating Local handle is like pushing
>> // value on the stack and destroying HandleScope is like poping
>> everything above remembered height.
>> v8::HandleScope handle_scope;
>> Local<String> v8_string = v8::String::New(s);
>> Local<Script> script = v8::Script::Compile(v8_string);
>> v8::TryCatch try_catch;
>> Local<Value> result = script->Run();
>> if (try_catch.HasCaught()) {
>> // exception is in try_catch.Exception()
>> v8::String::AsciiValue error_message(try_catch.Exception());
>> report(*error_message);} else {
>>
>> // returned value is in the result.
>>
>> }
>>
>> As you can see conversion is pretty much straighforward.
>>
>> --
>> Vyacheslav Egorov
>>
>> On Tue, Jan 18, 2011 at 4:35 PM, Jak Sprats <[email protected]> wrote:
>> > Hi Stephan,
>>
>> > this is very helpful, so thank you.
>>
>> > I am going to explain my use-case fully, because its pretty easy once
>> > explained, (I am a bad explainer) and forgive me if my explanations
>> > are overly simplistic, I am just a fanatic on clarity, so I write
>> > things as dumbed down as possible.
>>
>> > A.) AlchemyDB has SQL commands
>> > 1.) SELECT * FROM tbl WHERE user_id = 33 AND name = 'sally'
>> > 2.) UPDATE tbl SET count = count + 1 WHERE id = 1234
>> > B.) AlchemyDB has redis commands
>> > 1.) SET session_77 'name:bill;age:22'
>> > 2.) HGET user_77 name
>> > C.) AlchemyDB currently has some commands to call the embedded LUA
>> > This will add the file "functions.lua" to the embedded lua
>> > environment (used to populate lua libraries)
>> > 1.) CONFIG ADD LUA functions.lua
>> > This will pass the string 'return 1*2*3' to the embedded lua parser/
>> > executor which will perform the action '1*2*3' and pass the results
>> > back to AlchemyDB
>> > 2.) LUA 'return 1*2*3;'
>> > This will call AlchemyDB's SQL and Redis commands from w/in LUA
>> > First the session is checked for existence, and if it exists all
>> > rows from the table 'user_data' are returned, otherwise return an
>> > empty-string
>> > 3.) LUA 'sess = client('GET', 'session_77'); if (sess == nil)
>> > return "" else return client('SELECT','*','FROM',;user_data', ' WHERE
>> > id = 77'); end'
>>
>> > The lua function "client()" makes internal calls to AlchemyDB's SQL
>> > and redis commands, and is VERY useful for avoiding network hops, and
>> > placing trivial logic datastore side. Its like a sane stored
>> > procedures implementation.
>>
>> > I want to have the exact same thing in Javascript, because Javascript
>> > is really gaining in momentum, has 1000s of good libraries, and
>> > Node.js's Alchemy users would backflip at the possiblity of
>> > arbitrarily doing javascript logic at any point in their architecture.
>>
>> > So I need a very lightweight embedding of V8 and the single javascript
>> > function "client()" that can call C to internally reach into
>> > AlchemyDB.
>>
>> > I can have options to make AlchemyDB in C++ to be able to include V8,
>> > that is acceptable.
>>
>> > I understand everything you wrote, I am just a little bit leery of how
>> > much time it will take to figure out all the finer details of
>> > embedding one language in another in another, it was actually tricky
>> > to do w/ Lua, and lua is made for embedding ease. Any idea how many
>> > man-days embedding V8 and then using v8-juice to implement the JS func
>> > "client" would take? (just ballpark: is it a day, a week, a month?)
>>
>> > What would be REAL helpful is if there was a hello-world for embedding
>> > v8 in C and then using v8-juice to define a hello-world JS-calling-C
>> > function along w/ a how to compile and test for dummies, so I could
>> > start playing around w/ it. This is my work style, if I can build
>> > something, I can start glueing things together, but this initial
>> > learning curve of libraries internals/peculiarities takes me a long
>> > time.
>>
>> > thanks,
>> > Jak
>>
>> > On Jan 17, 7:10 am, Stephan Beal <[email protected]> wrote:
>> >> On Mon, Jan 17, 2011 at 2:51 PM, Jak Sprats <[email protected]> wrote:
>> >> > This seems to be what I am looking for ... some questions:
>> >> > 1.) AlchemyDB is written in ANSI-C, what are the requirements for your
>> >> > bindings (C++ at a minimum, any specifics on that)
>>
>> >> Whatever requirements v8 has, basically. i don't remember v8-juice have
>> >> any
>> >> requirements above what v8 needs.
>>
>> >> > 2.) I just need one function wrapped, the function is called
>> >> > "client()" and it can take between 1 and 6 arguments.
>>
>> >> The code demonstrated on that page accepts up to 10 arguments, and more
>> >> can
>> >> be generated via a script.
>> >> You don't need all of v8-juice for what you're doing: you can get by with
>> >> only some of the header files:
>>
>> >> Go
>> >> to:http://code.google.com/p/v8-juice/source/browse/#svn/trunk/src/includ...
>>
>> >> grab:
>>
>> >> - convert.h
>> >> - forwarding.h
>> >> - forwarding-*.h (generated code)
>> >> - TypeList.h
>> >> - TypeList_*.h ( generated code)
>>
>> >> And that should do it. The primary advantage, over using the whole
>> >> v8-juice
>> >> lib, is that you need only headers, not .cpp files. All of the type
>> >> conversion/function-forwarding code is templates, and implemented in their
>> >> header files.
>>
>> >> Your code should include convert.h and/or forwarding.h, and the rest are
>> >> implementation details. Those files assume an includes path of
>> >> <v8/juice/foo.h>, and you will need to replace those if you plan to use a
>> >> different structure.
>>
>> >> > And on a long shot, do you know of any C programs that embedded V8 and
>> >> > then the embedded v8 calls a C function via your bindings. This is
>> >> > what I am trying to reproduce in AlchemyDB (the C function would be
>> >> > "client()").
>>
>> >> i don't know of any programs which reach into v8 from C. i have
>> >> implemented
>> >> v8 add-ons on top of C libraries (like libcurl and libsqlite3), but that's
>> >> going the other direction. C cannot call directly into JS because it can't
>> >> use the objects needed by v8. It can, of course, use a C++ API which has
>> >> been wrapped in (extern "C" {...}), which then can pass on the calls to
>> >> v8.
>> >> So the call chain would look like: C -> C++ -> JS
>>
>> >> i hope this helps a bit,
>>
>> >> --
>> >> ----- stephan bealhttp://wanderinghorse.net/home/stephan/
>>
>> > --
>> > v8-users mailing list
>> > [email protected]
>> >http://groups.google.com/group/v8-users
>
> --
> v8-users mailing list
> [email protected]
> http://groups.google.com/group/v8-users
>
--
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users