4

I have some functions in Lua and some functions in C++ and I have managed to get the correct results from my addition, power and division. The only Problem I have is with the factorial, because I am not able to pass the correct number to it, which should be the result of the division.

in Lua:

function powLua(a, n)
   b = 1
   for i=1,n do b = b * a end
   return b
end

function divisionLua(a, b)
   c = b/a
   return c
end

aLua = additionLua(2, 3)
bLua = additionLua(1, 3)

print("Result of additionLua is a = "..aLua.."\nResult of additionLua is b = "..bLua.."\n")

fac = factorialLua(divLua) <---- this is the part that doesn't work

print("factorial of divLua is "..fac.."\n")

in C++:

int addition(lua_State* L)
{
    int x = lua_tonumber(L, 1);
    int y = lua_tonumber(L, 2);

    lua_pushnumber(L, x + y);

    return 1;
}

int fac_calc(int x)
{
    if (x <= 1)
        return 1;

    return x * fac_calc(x-1);
}

int factorial(lua_State* L)
{   
    int fac = lua_tonumber(L, 1);

    lua_pushnumber(L, fac_calc(fac));

    return 1;
}

int power(lua_State* L, int a, int n)
{
    int b;

    lua_getglobal(L, "powLua");
    lua_pushnumber(L, a);
    lua_pushnumber(L, n);

    if (lua_pcall(L, 2, 1, 0) != 0)
        printf("error running function 'powLua': %s", lua_tostring(L, -1));

    if (!lua_isnumber(L, -1))
        printf("function `powLua' must return a number\n");
    b = lua_tonumber(L, -1);
    lua_pop(L, 1);  /* pop returned value */
    return b;
}

int division(lua_State* L, int a, int b)
{
    int c;

    lua_getglobal(L, "divisionLua");
    lua_pushnumber(L, a);
    lua_pushnumber(L, b);

    lua_pcall(L, 2, 1, 0);

    c = lua_tonumber(L, -1);
    lua_pop(L, -1);

    return c;
}

int main(int argc, char* argv[])
{
    lua_State* L = luaL_newstate();

    luaL_openlibs(L); 

    lua_pushcfunction(L, addition); 
    lua_setglobal(L, "additionLua"); 

    lua_pushcfunction(L, factorial);
    lua_setglobal(L, "factorialLua");

    luaL_dofile(L, "test01.lua");

    lua_getglobal(L, "aLua");
    int a = lua_tonumber(L, -1);
    lua_pop(L, -1);

    lua_getglobal(L, "bLua");
    int b = lua_tonumber(L, -1);
    lua_pop(L, -1);

    int pwr = power(L, a, b);

    int div = division(L, a, pwr);
    lua_pushnumber(L, div);
    lua_setglobal(L, "divLua");

    cout << "Result of a^b in powLua is pwr: " << a << "^" << b << " = " << pwr << endl;

    cout << "Result of pwr/a in divisionLua is: " << pwr << "/" << a << " = " << div << endl;

    lua_close(L);
}

my Output is this:

Result of additionLua is a = 5

Result of additionLua is b = 4

factorial of divLua is 1

Result of a^b in powLua is pwr: 5^4 = 625

Result of pwr/a in divisionLua is: 625/5 = 125

I guess I have to push the result of the division onto the stack before I open the "test01.lua" file, but it didn't work either.

I have also succesfully testet the factorial function by giving it a direct value. For example factorialLua(5) gives me an output of 120.

Does anybody know where my mistake is?

Edit:

Setting "divLua" before running the script with a testvalue like this:

int div = 5;
lua_pushnumber(L, div);
lua_setglobal(L, "divLua");
...
...
luaL_dofile(L, "test01.lua");

leads to the correct result of factorialLua(divLua), however when I set "divLua" as a value of division(), like this:

int div = division(L, 5, 30); //div should be 6 now
lua_pushnumber(L, div);
lua_setglobal(L, "divLua");
...
...
luaL_dofile(L, "test01.lua");

the result of factorialLua(divLua) is 1 and not 720 how it should be.

The reason must be that division() has to be called after the luaL_dofile, but lua_setglobal(L, "divLua") has to be before of it. So I need to let "div" know the result of a calculation which will be done later.

Any suggestions?

1 Answer 1

5

There are a couple of issues above:

  • You're trying to compute factorialLua(divLua) in the script before divLua is set from C++.
  • You're calling lua_pop with a negative index but it expects a positive integer.
  • Assuming the first two points are addressed, you're trying to compute 125! which is going to be a really large number.

Note, the reason you're currently getting 1 for factorialLua is because lua_tonumber returns 0 if the given stack index isn't actually a number. Since divLua is still nil when this was called, you are effectively computing factorialLua(0).

The two obvious ways to go about fixing this:

  1. Do a lua_setglobal(L, "divLua") before you actually execute your script.
  2. Move your factorial computation into C++ land to a point where divLua is actually defined.
Sign up to request clarification or add additional context in comments.

2 Comments

(I'd add that one can use luaL_checknumber instead of lua_tonumber to catch the last problem.)
Thank you for your quick answer. I've changed the lua_pop calls, didn't realise that mistake. I have then set divLua global before executing my script with luaL_dofile. I had already tried that and I know that you're right, but if I do that it doesn't recognise the Parameters for the Division, which are pwr and a, because they have to be set after executing the script. At least it doesn't work if I declare them before execution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.