Accessing Lua global tables with C++ - c++

How can I access a global table that already exists in Lua using C++ ?
Below are code which I tried. I tried creating a global variable and try modifying a that local to the local in Lua but things dont seem to work
lua_State *lua_state = luaL_newstate();
luaL_openlibs(lua_state);
// lua_createtable(lua_state, 0, 81);
// for (int i = 1; i <= 81; i++)
// {
// lua_pushnumber(lua_state, i);
// lua_pushnumber(lua_state, grid_[i - 1]);
// lua_settable(lua_state, -3);
// }
//
// lua_setglobal(lua_state, "arg");
// lua_createtable(lua_state, 81, 1);
//
// for (int i = 1; i <= 81; i++)
// {
// lua_pushnumber(lua_state, i);
// lua_pushnumber(lua_state, grid_[i - 1]);
// lua_settable(lua_state, -3);
// }
// lua_setglobal(lua_state, "arg");
luaL_loadfile(lua_state, "main.lua");
lua_call(lua_state, 0, 0);
int t = 2;
/* table is in the stack at index 't' */
lua_pushnil(lua_state); /* first key */
while (lua_next(lua_state, t) != 0) {
/* uses 'key' (at index -2) and 'value' (at index -1) */
printf("%s - %s\n",
lua_typename(lua_state, lua_type(lua_state, -2)),
lua_typename(lua_state, lua_type(lua_state, -1)));
/* removes 'value'; keeps 'key' for next iteration */
lua_pop(lua_state, 1);
}
Lua
problem =
{
{9, 0, 0, 1, 0, 0, 0, 0, 5},
{0, 0, 5, 0, 9, 0, 2, 0, 1},
{8, 0, 0, 0, 4, 0, 0, 0, 0},
{0, 0, 0, 0, 8, 0, 0, 0, 0},
{0, 0, 0, 7, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 2, 6, 0, 0, 9},
{2, 0, 0, 3, 0, 0, 0, 0, 6},
{0, 0, 0, 2, 0, 0, 9, 0, 0},
{0, 0, 1, 9, 0, 4, 5, 7, 0},
}
Update 1
int main()
{
lua_State *lua_state = luaL_newstate();
luaL_openlibs(lua_state);
luaL_loadfile(lua_state, "main.lua");
lua_getglobal(lua_state, "problem");
//lua_pushglobaltable(lua_state); // Get global table
lua_pushnil(lua_state); // put a nil key on stack
while (lua_next(lua_state, -2) != 0) { // key(-1) is replaced by the next key(-1) in table(-2)
std::string name = lua_tostring(lua_state, -2); // Get key(-2) name
std::cout << name << std::endl;
lua_pop(lua_state, 1); // remove value(-1), now key on top at(-1)
}
lua_pop(lua_state, 1); // remove global table(-1)
lua_call(lua_state, 0, 0);
return 0;
}
Lua
problem =
{
{9, 0, 0, 1, 0, 0, 0, 0, 5},
{0, 0, 5, 0, 9, 0, 2, 0, 1},
{8, 0, 0, 0, 4, 0, 0, 0, 0},
{0, 0, 0, 0, 8, 0, 0, 0, 0},
{0, 0, 0, 7, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 2, 6, 0, 0, 9},
{2, 0, 0, 3, 0, 0, 0, 0, 6},
{0, 0, 0, 2, 0, 0, 9, 0, 0},
{0, 0, 1, 9, 0, 4, 5, 7, 0},
}
print("Lua Works")
user_input = io.read();

You don't have any values to iterate on Lua stack.
That int t=2; doesn't reflect anything, and your script doesn't return values to be left on stack.
See PIL book: 25.1 – Table Manipulation for examples on accessing global table.

Related

The safest way to add integer into array value without having to call it?

What is the safest way to add integer into array value without having to call the array value ? In this case I would rather not to call the array value because the array is inside a nested loop and the loop itself can repeat for thousands times.
For example dots[1] = I want to add value of this array with 3. Here's my sample code :
void box(const Mat &dots, Mat &newdots, int rows, int cols)
{
for (int i = 0; i < dots.rows; i++) {
for (int j = 0; j < dots.cols; j++) {
newdots.at<Vec3b>(i, j)[0] = dots.at<Vec3b>(i, j)[0];
newdots.at<Vec3b>(i, j)[1] = dots.at<Vec3b>(i, j)[1]; //add this with 3
newdots.at<Vec3b>(i, j)[2] = dots.at<Vec3b>(i, j)[2]; //add this with 5
}
}
Is it possible ? Any suggestion how to do it ? Thanks.
This simplest way is to use cv::add, which overloads the + operator for the Mat class:
// Create a Mat of all 0's
cv::Mat dots = cv::Mat(5, 4, CV_8UC3, cv::Scalar(0,0,0));
std::cout << "dots:\n" << dots << std::endl;
// Add 0 to the B channel, 3 to the G channel, and 5 to R
cv::Mat newdots = dots + cv::Scalar(0, 3, 5);
std::cout << "newdots:\n" << newdots << std::endl;
Result:
dots:
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
newdots:
[ 0, 3, 5, 0, 3, 5, 0, 3, 5, 0, 3, 5;
0, 3, 5, 0, 3, 5, 0, 3, 5, 0, 3, 5;
0, 3, 5, 0, 3, 5, 0, 3, 5, 0, 3, 5;
0, 3, 5, 0, 3, 5, 0, 3, 5, 0, 3, 5;
0, 3, 5, 0, 3, 5, 0, 3, 5, 0, 3, 5]
Note that dots += Scalar(0,3,5) also works if you just want to modify the original Mat.

Opencv Matrix Range L value : Is this a bug?

It seems to me that using Matrix with Ranges as an L-value (assignment target) should work or not (and if not a compiler error would be nice) but not both depending on the particulars of a legitimate r-value.
cout << "hi mom" << endl;
Mat Img0=Mat::zeros(7,7,CV_8UC1);
Mat Img1=Mat::ones(7,7,CV_8UC1);
cout << Img0 << endl;
cout << Img1 << endl;
Img0(Range::all(), Range::all()) = Img1;
cout << Img0 << endl;
Img0(Range::all(), Range::all()) = 1;
cout << Img0 << endl;
Below is the output from the above. The first two matrix print outs are of Img0 and Img1 as initialized by Mat::zeros and Mat::ones respectively.
The third matrix print out is Img0 again but after
Img0(Range::all(), Range::all()) = Img1;
which I expected would set Img0 to Img1; i.e. all ones; but it's not. It's still all zeros.
The fourth/last matrix print out is the result of
Img0(Range::all(), Range::all()) = 1;
Which has the same L value as the third assignment but it works when a scalar is the Rvalue (unlike the third which as a matrix as the RValue).
Is there some sense in this that I'm missing? Should this r-value distinction behavior be allowed? It seems inconsistent to me.
[0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1]
[0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1;
1, 1, 1, 1, 1, 1, 1]
No, this is not a bug.
This line Img0(Range::all(), Range::all()) = Img1; doesn't work as expected because Img0(Range::all(), Range::all()) forms a temporary header that is further assigned to another header, which is Img1. Remember that each of these operations is O(1), that is, no data is copied. Thus, no real assignment happens.
You can realize this effect more clearly by doing this:
(Img0(Range::all(), Range::all()) = Img1) = 2;
cout << Img0 << endl;
cout << Img1 << endl;
If you have understood what I described above, you should be aware of that the code will only change the value of Img1. And the output is:
[0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0]
[2, 2, 2, 2, 2, 2, 2;
2, 2, 2, 2, 2, 2, 2;
2, 2, 2, 2, 2, 2, 2;
2, 2, 2, 2, 2, 2, 2;
2, 2, 2, 2, 2, 2, 2;
2, 2, 2, 2, 2, 2, 2;
2, 2, 2, 2, 2, 2, 2]
Further reading: check out similar effect happened to Mat::row().

Assigning to an array from an initializer list [duplicate]

This question already has answers here:
Error: Assigning to an array from an initializer list
(2 answers)
Closed 9 years ago.
I've checked on SO already for a simple way to fix this error. I didn't get this when compiling on another computer but suddenly now it's not compiling on my PC. Here's the error I'm getting:
Error: Assigning to an array from an initializer list
And here's the code:
int maze[12][12];
void print(bool playing);
int main()
{
printMaze(false);
playGame();
return 0;
}
void print(bool playing)
{
if (!playing) maze = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1},
{2, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1},
{1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1},
{1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 3},
{1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1},
{1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1},
{1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1},
{1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};
}
It might also be worth mentioning that I get a warning on the same line:
Warning: Extended initializer lists only available with -std=c++11 or -std=gnu++11 [enabled by default]
I know that clearly means I have to use one of these two to use extended initializer lists, but have no idea what to do to resolve the matter.
Edit:
Having g++ follow the C++11 ISO C++ language standard in the settings removes the warning, but not the error.
What do your compilations steps look like? The warning is fairly clear: you are trying to use a feature that requires -std=c++11 or -std=gnu++11, and although that is apparently enabled by default, it is possible that you have overridden it (i.e. explicitly turned it off) somehow. You should examine your compilation process closer and make sure you aren't preventing that feature from being allowed.
A workaround is to use the old-style C function memcpy. This will work with older compilers.
int maze[12][12];
void printMaze(bool playing);
int main()
{
printMaze(false);
playGame();
return 0;
}
void printMaze(bool playing)
{
static int maze1[12][12] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1},
{2, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1},
{1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1},
{1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 3},
{1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1},
{1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1},
{1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1},
{1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};
if (!playing) memcpy(maze, maze1, 12*12*sizeof(int));
}

Adding two arrays?

In the Arduino IDE, I'd like to add the contents of two existing arrays like this:
#define L0 { {0, 0, 0, 0}, {0, 0, 0, 1}, {0, 0, 0, 0} }
#define L1 { {0, 0, 0, 1}, {0, 0, 0, 0}, {0, 0, 0, 0} }
should become
int myarray[3][4] = { {0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 0} }
How would I go about this?
Thanks!
Thy this;
const int a[3][4] = { {0, 0, 0, 0}, {0, 0, 0, 1}, {0, 0, 0, 0} };
const int b[3][4] = { {0, 0, 0, 1}, {0, 0, 0, 0}, {0, 0, 0, 0} };
int c[3][4];
const int* pa = &a[0][0];
const int* pb = &b[0][0];
int* pc = &c[0][0];
for(int i = 0; i < 3 * 4; ++i)
{
*(pc + i) = *(pa + i) + *(pb + i);
}
I think you are confused about how to go access the arrays L0 and L1 since they are defined as macros. Just assign them to arrays since the preprocessor will simply replace them:
int l[][4]=L0;
int m[][4]=L1;
Preprocessor will replace L0 and L1 with their values and compiler will only see them as:
int l[][4]={ {0, 0, 0, 0}, {0, 0, 0, 1}, {0, 2, 0, 0} };
int m[][4]={ {0, 0, 0, 5}, {0, 0, 0, 6}, {0, 0, 7, 0} };
Now, you can use l & m to access the elements of array. Should easy enough from here to add two arrays :)

Checking whether a number exist in the same row or column

I have been staring at this code for few hours, tried walkthrough,debugging with autos and breakpoints and it's no solution so far. Maybie someone's fresh look would help me ;) .
#include <iostream>
using namespace std;
int matrix[9][9] = {{0, 0, 6, 0, 0, 0, 1, 0, 5},
{0, 4, 0, 7, 0, 6, 0, 3, 9},
{2, 0, 0, 9, 3, 0, 6, 0, 0},
{7, 0, 0, 1, 8, 0, 5, 0, 4},
{0, 0, 4, 0, 6, 0, 9, 0, 0},
{1, 0, 9, 0, 5, 2, 0, 0, 3},
{0, 0, 1, 0, 9, 3, 0, 0, 7},
{6, 7, 0, 5, 0, 8, 0, 9, 0},
{9, 0, 8, 0, 0, 0, 4, 0, 0}};
bool check(int column ,int row,int checkedValue)
{
//column check
for(int i=0; i<9; i++)
{
if(i==row)continue;
if(checkedValue==matrix[column][i]) return false;
}
//row check
for(int i=0; i<9; i++)
{
if(i==column) continue;
if(checkedValue==matrix[i][row]) return false;
}
return true;
}
int main()
{
cout<<check(4,0,4); //Why does it output 0? There is no "4" in the 5th column and the 1st row.
system("pause");
return 0;
}
The function check(column,row,value) was designed to return 0 when number occurs at least once in the "matrix" two dimensional table. This program is a chunk of sudoku solver.
You mixed the indices up in the if statements. They should be:
if(checkedValue==matrix[i][column]) return false; // not matrix[column][i]
and
if(checkedValue==matrix[row][i]) return false; // not matrix[i][row]
The reason is that the first dimension is the row. You can check this by printing matrix[2][0].
For your matrix, you will get 2 (and not 6).