views:

129

answers:

3

Hi guys,

I need a very simple c++ function that calls a lua function that returns an array of strings, and stores them as a c++ vector. The function can look something like this:

std::vector<string> call_lua_func(string lua_source_code);

(where lua source code contains a lua function that returns an array of strings).

Any ideas?

Thanks!

+1  A: 

First of all, remember Lua arrays can contain not only integers but also other types as keys.

Then, you can import the Lua source code using luaL_loadstring.

At this point, the only requirement left is the "return vector". Now, you can use lua_istable to check whether a value is a table(array) and use lua_gettable to extract the multiple fields(see http://www.lua.org/pil/25.1.html) and manually add them one by one to the vector.

If you can not figure out how to deal with the stack, there seem to be some tutorials to help you. To find the number of elements, I found this mailing list post, which might be helpful.

Right now, I don't have Lua installed, so I can't test this information. But I hope it helps anyway.

luiscubal
A: 

Not really an answer to your question:
I've had a lot of trouble when writing c++ <=> lua interface code with the plain lua c-api. Then I tested many different lua-wrapper and I really suggest luabind if you are trying to achieve anything more or less complex. It's possible to make types available to lua in seconds, the support for smart pointers works great and (compared to other projects) the documentation is more or less good.

Daniel
A: 

Here is some source that may work for you. It may need some more polish and testing. It expects that the Lua chunk is returning the array of strings, but with slight modification could call a named function in the chunk. So, as-is, it works with "return {'a'}" as a parameter, but not "function a() return {'a'} end" as a parameter.

extern "C" {
#include "../src/lua.h"
#include "../src/lauxlib.h"
}

std::vector<string> call_lua_func(string lua_source_code)
{
  std::vector<string> list_strings;

  // create a Lua state
  lua_State *L = luaL_newstate();
  lua_settop(L,0);

  // execute the string chunk
  luaL_dostring(L, lua_source_code.c_str());

  // if only one return value, and value is a table
  if(lua_gettop(L) == 1 && lua_istable(L, 1))
  {
    // for each entry in the table
    int len = lua_objlen(L, 1);
    for(int i=1;i <= len; i++)
    {
      // get the entry to stack
      lua_pushinteger(L, i);
      lua_gettable(L, 1);

      // get table entry as string
      const char *s = lua_tostring(L, -1);
      if(s)
      {
        // push the value to the vector
        list_strings.push_back(s);
      }

      // remove entry from stack
      lua_pop(L,1);
    }
  }

  // destroy the Lua state
  lua_close(L);

  return list_strings;
}
gwell
Thanks a lot! Your code helped me a ton! But I forgot one thing, maybe you could help me with that as well: I need the lua function to also receive a string from c++, so I need one extra step of pushing a string argument and accessing it from the lua function. It would be awesome if you could help. Thanks again!!
Koko
Push the string on the stack before the call to `luaL_dostring()` using `lua_pushstring(L, argument.c_str());` then change `luaL_dostring()` to `if(0 == luaL_loadstring(L, lua_source_code.c_str())) lua_pcall(L, 1, 1, 0));`
gwell