Nested table built with Lua C API crashes - lua

I'm trying to make a deeply nested table in Lua. When I nest past 16 levels my program crashes.
In the example program below, when I change DEPTH to 16 instead of 17 the program does not crash. I can't find any resources that say there is a maximum table depth, and one so low seems odd. The crash is within the call to lua_close().
Am I misunderstanding how to build a table in Lua using the C API, or is there in fact a maximum depth?
#include <assert.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#define DEPTH 17
int main(int argc, char* argv[])
{
lua_State *L = NULL;
size_t i = 0;
L = luaL_newstate();
assert(NULL!=L);
luaL_openlibs(L);
// create the root table
lua_newtable(L);
// push DEPTH levels deep onto the table
for (i=0; i<DEPTH; i++)
{
lua_pushstring(L, "subtable");
lua_newtable(L);
}
// nest the DEPTH levels
for (i=0; i<DEPTH; i++)
{
lua_settable(L, -3);
}
lua_close(L);
return 0;
}

You need to increase the stack with lua_checkstack or luaL_checkstack to allow 2*DEPTH slots.

Related

Get size of an array in C++ 17 using pass by reference

Is there a way to find the size of an array, using pass by reference. The size function works well inside the main function.
#include <iostream>
#include <iterator>
using namespace std;
int hello(int arr[]){
cout<<arr<<endl;
//cout<<size(arr)<<endl;
}
int main(){
int arr[] = {1,2,3,4,6,7,2};
hello(arr);
cout<<arr<<endl;
cout<<size(arr)<<endl;
}
You are passing array by value so hello function takes as its parameter decayed type - int*.
When you pass array by reference, you need to pass one additional non-type template parameter which is length of array and is deduced, therefore inside hello you don't even use std::size to get array's length, just use N:
template<class T, size_t N>
int hello(T (&arr)[N])
{
cout<< size(arr) <<endl; // 7
cout << N << endl; // 7
return 0;
}
Once you pass an array to a function, it becomes a pointer, and there is no way to get the size from that (it will always report 4 or 8 bytes - the size of a pointer value!).
If you need to process an array in a func, you will need to pass in the size as an argument to the function.
#include <iostream>
#include <iterator>
using namespace std;
int hello(int arr[], size_t count)
{
for(size_t i = 0; i < count; ++i)
{
std::cout << arr[i] << std::endl;
}
}
int main(){
int arr[] = {1,2,3,4,6,7,2};
hello(arr, sizeof(arr) / sizeof(int));
return 0;
}
The better alternative in C++, is to use std::vector instead. (which will store the size as a member variable)
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
void hello(const std::vector<int>& arr)
{
for(size_t i = 0; i < arr.size(); ++i)
{
std::cout << arr[i] << std::endl;
}
}
int main(){
std::vector<int> arr = {1,2,3,4,6,7,2};
hello(arr);
return 0;
}

How do I set all odd rows of a cv::Mat to a scalar value?

I would like to set all odd rows of an nxm cv::Mat to a scalar value. There are brute force approaches to this problem, but I would like to know if there is something more elegant.
Extending from this problem, I would like to set all even rows of a different channel to a scalar value.
There are no OpenCV built-in functions that do this, but this can be done easily in 3 lines of code.
#include <opencv2\opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
// The new value for the rows
uchar some_value = 100;
// Your matrix (here random initialized)
Mat1b mat(5, 3, uchar(0));
randu(mat, 0, 10);
// Set all even rows to some_value
for (int r = 0; r < mat.rows; r += 2) {
for (int c = 0; c < mat.cols; ++c) {
mat(r, c) = some_value;
}
}
return 0;
}
Yes, this is probably you called "brute force", but this is the method with fewer accesses to the matrix.
It's also very fast, you can eventually implement it with pointers to be even faster (here an example with 3 channels):
#include <opencv2\opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Vec3b some_value(100, 101, 102);
Mat3b mat(5, 3, Vec3b(0,0,0));
randu(mat, Scalar(0, 0, 0), Scalar(10, 10, 10));
for (int r = 0; r < mat.rows; r += 2) {
Vec3b* ptr = mat.ptr<Vec3b>(r);
for (int c = 0; c < mat.cols; ++c) {
ptr[c] = some_value;
}
}
return 0;
}
You can also create a mask with odd rows white (255), and even rows black (0), and use cv::setTo to set values according to the mask. This however is probably much slower, because you need to i) create the mask, and ii) access each pixel in the matrix (probably exploiting optimized code, though).
Not sure of speed but I guess OP referred to elegance that of MATLAB matrix operations, and sure some of them have been imported to OpenCV, e.g.
cv::Mat m(8,15,CV_32FC1,cv::Scalar(0));
for (int i=0;i<m.rows;i+=2)
m.row(i).setTo( 32 );
Likewise, you can construct a cv::Mat header for each column separately using cv::Mat::col(int i) function.

cudaMemcpy invalid argument: in simple vector example

The following example:
#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>
#include <cuda.h>
#include <math.h>
#define N 100
#define t_num 256
int main(){
int vector_one_h[t_num], vector_one_g[t_num];
cudaError_t err = cudaMalloc((void**)&vector_one_g, t_num * sizeof(int));
printf("Cuda malloc vector swap one: %s \n", cudaGetErrorString(err));
printf("Device Vector: %p \n:" , vector_one_g);
for(int m = 0; m < t_num; m++){
vector_one_h[m] = rand() % N;
}
err = cudaMemcpy(vector_one_g, vector_one_h, t_num * sizeof(int), cudaMemcpyHostToDevice);
printf("Cuda mem copy vector swap one: %s \n", cudaGetErrorString(err));
}
Will return:
Cuda malloc vector swap one: no error
Device Vector: 0x7ffcf028eea0
:Cuda mem copy vector swap one: invalid argument
So why is cudaMemcpy receiving an invalid argument?
From the documentation for cudaMemcpy() here I thought the problem may be that I need to give the second argument as the address, &vector_one_h, but placing that in the code returns the exact same error.
And also, while there are many posts about cudaMemcpy invalid arguments, I believe this is not a duplicate as most of the other questions have very complicated examples while this is a very simple and minimal example.
Try changing the first line to:
int vector_one_h[t_num], *vector_one_g;
BTW, prefixing an array name with an & has no effect. Array names are constant pointers by themselves, by the definition of C syntax.

OpenCV: fast matrix computation

I have an nxd matrix V=[v_1; v_2;...; v_n] (; means new row) where v_i are 1xd vectors.
I want to compute the following sum: v_1^T*v_1 + v_2^T*v_2 + ... + v_n^T*v_n, which is a dxd matrix (v_i^T is the transpose of v_i).
For the moment I use a for loop, as in the code below, which is not efficient when n is very large (I think so).
#include <iostream>
#include <opencv2/core.hpp>
using namespace cv;
using namespace std;
int main (int argc, char * argv[])
{
int n=5, d=3;
Mat V = Mat(n, d, CV_32F);
randu(V, Scalar::all(0), Scalar::all(10));
cout<<V<<endl<<endl;
Mat M = Mat::zeros(d, d, CV_32F);
for(int i=0; i<n; i++)
{
M = M + V.row(i).t()*V.row(i);
}
cout<<M<<endl<<endl;
return 0;
}
Hope that somebody can suggest a faster way. Thanks in advance.
You can just take V.t()*V
(It took me a minute to realize it too, but if you go through the matrix multiplication you'll see it's the same)

lua5.2's error: multiple Lua VMs detected

I use 5.2 for learning recently, what I want to try like this:
Step 1, build a c module for lua:
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include <stdlib.h>
static int add(lua_State *L) {
int x = luaL_checkint(L, -2);
int y = luaL_checkint(L, -1);
lua_pushinteger(L, x + y);
return 1;
}
static const struct luaL_Reg reg_lib[] = {
{"add", add}
};
int luaopen_tool(lua_State *L) {
luaL_newlib(L, reg_lib);
lua_setglobal(L, "tool");
return 0;
}
I compile and link it with liblua.a, and I'm sure it works well in lua script like "require("tool") tool.add(1, 2)"
Step 2, I write another C program that wants to require my c module in step 1 like this:
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include <stdlib.h>
int main(int argc, char* const argv[]) {
lua_State *L = luaL_newstate();
luaL_requiref(L, "base", luaopen_base, 1);
luaL_requiref(L, "package", luaopen_package, 1);
lua_getglobal(L, "require");
if (!lua_isfunction(L, -1)) {
printf("require not found\n");
return 2;
}
lua_pushstring(L, "tool");
if (lua_pcall(L, 1, 1, 0) != LUA_OK) {
printf("require_fail=%s\n", lua_tostring(L, -1));
return 3;
}
lua_getfield(L, -1, "add");
lua_pushinteger(L, 2);
lua_pushinteger(L, 3);
lua_pcall(L, 2, 1, 0);
int n = luaL_checkint(L, -1);
printf("n=%d\n", n);
return 0;
}
I also compile & link with liblua.a, but error occurs when I run it:
"require_fail=multiple Lua VMs detected"
Someone's blog said that in lua5.2, you should link c module and c host program both dynamicly, but not staticly.
is there someone that has the same problem, or is there somehing wrong in my code, thanks.
NOTICE:
the problem has been solved by compile main program with -Wl,-E, thanks a lot for all your help ^^.
Don't link your C module with liblua.a when you create a .so from it. For examples, see my page of Lua libraries: http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/ . You can link liblua.a statically into your main program but you have to export its symbols by adding -Wl,-E at link time. That's how the Lua interpreter is built in Linux.

Resources