I'm trying to use a lua state within C++ and i need to pass it a str from C++, how ever when i try to call my function i wrote in lua, i get the error
attempted to call nil value. It compiles straight into the lua environment, but when i type the expression in i get the error.
int main(int argc, char** argv){
lua_State *L;
L = luaL_newstate();
string buff;
const char* finalString;
luaL_openlibs(L);
luaL_dofile(L,argv[1]);
getline(cin, buff);
lua_getglobal(L, "InfixToPostfix");
lua_pushstring (L, buff.c_str());
lua_pcall(L, 1, 1, 0);
finalString = lua_tostring(L, -1);
printf("%s\n", finalString);
lua_close(L);
}
from lua file:
function InfixToPostfix(str)
print("before for loop")
for i in string.gmatch(str, "%S+") do
it wont reach the print out before displaying error
The following works for me just fine:
#include <iostream>
#include <string>
#include <lua.hpp>
int main(int argc, char** argv)
{
lua_State *L;
L = luaL_newstate();
luaL_openlibs(L);
if (argc != 2)
{
std::cerr << "Usage: " << argv[0] << " script.lua\n";
return 1;
}
if ( luaL_dofile(L,argv[1]) != 0 )
{
std::cerr << lua_tostring(L, -1) << '\n';
return 1;
}
std::string buff;
std::getline(std::cin, buff);
lua_getglobal(L, "InfixToPostfix");
lua_pushstring (L, buff.c_str());
if ( lua_pcall(L, 1, 1, 0) != 0)
{
std::cerr << lua_tostring(L, -1) << '\n';
return 1;
}
if ( !lua_isstring(L, -1) )
{
std::cerr << "Error: Return value cannot be converted to string!\n";
return 1;
}
const char * finalString = lua_tostring(L, -1);
std::cout << finalString << '\n';
lua_close(L);
}
function InfixToPostfix(str)
print("before for loop")
for i in string.gmatch(str, "%S+") do
print(i)
end
return "Something"
end
For the C++ part you could also use the Selene library. This considerably reduces the amount of code needed, also no manual error checking is needed.
#include <iostream>
#include <string>
#include <selene.h>
int main(int argc, char** argv)
{
sel::State L{true};
if (argc != 2)
{
std::cerr << "Usage: " << argv[0] << " script.lua\n";
return 1;
}
L.Load(argv[1]);
std::string buff;
std::getline(std::cin, buff);
std::string finalString = L["InfixToPostfix"](buff);
std::cout << finalString << '\n';
}
Related
I need to input error statements above exits three and four and then actually force the code to go to these error statements so I can have screenshot proof that they are working. However, I can't quite work out what should be in each. My initial thoughts are 'the output file can't be created for 3 and 'The file you want to read from is empty' for 4, but I can't seem to trigger these errors so I feel like that's not correct.
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#define BUF_SIZE 500
#define OUTPUT_MODE 0700
int main(int argc, char *argv[])
{
int in_file, out_file;
int read_size = 1, write_size;
char buf[BUF_SIZE];
if (argc != 3){
cout<<"The command-line input does not contain 3 arguments"<<endl;
exit(1);
}
in_file= open(argv[1], O_RDONLY);
if (in_file < 0) {
cout<<"The file you are trying to copy from doesnt exist"<<endl;
exit(2);
}
out_file = creat(argv[2], OUTPUT_MODE);
if (out_file < 0) {
cout<<"Error statement 3"<<endl;
exit(3);
}
while (read_size > 0) {
read_size = read(in_file, buf, BUF_SIZE);
if (read_size <0){
cout<<"Error statement 4"<<endl;
exit(4);
}
write_size = write(out_file, buf, read_size);
if (write_size<=0){
close(in_file);
close(out_file);
cout<<"Reading and writing from and to files is complete"<<endl;
exit(5);
}
}
}
The way to work out how these functions can /will fail, is to read the documentation for them.
https://man7.org/linux/man-pages/man2/read.2.html
https://man7.org/linux/man-pages/man2/open.2.html
(note, the documentation of creat says its equivalent to calling open with specific arguments)
At the bottom, it lists what errno will be set to and why.
Open, for example, will fail on a read only disk.
Most standard library functions will set errno to give you the reason they failed. Use that information, and write your error messages to stderr:
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#define OUTPUT_MODE 0700
int
main(int argc, char *argv[])
{
int in_file, out_file;
int read_size, write_size;
char buf[BUFSIZ];
if (argc != 3){
cerr << "Missing arguments" <<endl;
exit(EXIT_FAILURE);
}
in_file= open(argv[1], O_RDONLY);
if( in_file < 0 ){
cerr << argv[1] << ": " << strerror(errno) << endl;
exit(EXIT_FAILURE);
}
out_file = creat(argv[2], OUTPUT_MODE);
if( out_file < 0 ){
cerr << argv[2] << ": " << strerror(errno) << endl;
exit(EXIT_FAILURE);
}
while( (read_size = read(in_file, buf, BUFSIZ)) > 0 ){
const char *s = buf;
do {
write_size = write(out_file, s, read_size);
read_size -= write_size;
if( write_size <= 0 ){
cerr << argv[2] << ": " << strerror(errno) << endl;
exit(EXIT_FAILURE);
}
s += write_size;
} while( read_size > 0);
}
if( read_size < 0 ){
cerr << argv[1] << ": " << strerror(errno) << endl;
exit(EXIT_FAILURE);
}
close(in_file);
close(out_file);
}
My problem is that is access the kinect with the following code:
#include "libfreenect.hpp"
#include <iostream>
freenect_context* ctx;
freenect_device* dev;
void freenect_threadfunc(freenect_device* dev, void* v_depth, uint32_t timestamp){
short* d = (short*) v_depth;
std::cout << d[0] << std::endl;
}
int main(int argc, char const *argv[])
{
if(freenect_init(&ctx, NULL) < 0){
std::cout << "freenect_init() failed!" << std::endl;
}
if (freenect_open_device(ctx, &dev, 0) < 0){
std::cout << "No device found!" << std::endl;
freenect_shutdown(ctx);
}
freenect_set_depth_callback(dev, freenect_threadfunc);
freenect_set_depth_mode(dev, freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT));
freenect_start_depth(dev);
while (true) {
}
return 0;
}
But for some reason i don't know, the callback function ´freenect_threadfunc´ doesn't execute. When executing freenect-glview which is a example provided by Openkinect, everything works fine.
Thank you for your help.
I am trying to use libuv to launch a process in a cross-platform way. To test the library, I have written a small C++ application that calls sleep 1 and then exits. The problem is that sometimes (~5% of the time) it crashes with the following error from libuv:
EFAULT bad address in system call argument
Here is my code:
#include <iostream>
#include <string>
#include <memory>
#include <cstring>
#include <uv.h>
char* a;
char* b;
char** args;
std::string error_to_string(int const& error) {
return std::string(uv_err_name(error)) +
" " +
std::string(uv_strerror(error));
}
void on_exit(uv_process_t* req, int64_t exit_status, int term_signal) {
std::cout << "I'm back! " << std::endl;
std::cout << "exit_status " << exit_status
<< " term_signal " << term_signal << std::endl;
uv_close((uv_handle_t*)req, nullptr);
}
int main(int argc, const char** argv) {
auto* loop = new uv_loop_t();
uv_loop_init(loop);
auto* process = new uv_process_t();
uv_process_options_t options = {};
a = new char[100];
b = new char[100];
strcpy(a, "sleep\0");
strcpy(b, "1\0");
args = new char*[2];
args[0] = a;
args[1] = b;
options.exit_cb = on_exit;
options.file = "sleep";
options.args = args;
std::cout << "Going to sleep..." << std::endl;
int const r = uv_spawn(loop, process, &options);
if (r < 0) {
std::cout << error_to_string(r) << std::endl;
return 1;
}
uv_run(loop, UV_RUN_DEFAULT);
return 0;
}
I am using libuv 1.11.0, Clang 4.0.1 and C++ 14.
Can you spot my mistake?
Your args array is set up wrong. It should be:
args = new char*[3];
args[0] = a;
args[1] = b;
args[2] = NULL;
Otherwise uv_spawn doesn't know where the end of the array is.
I've never used string or string functions until today and I'm running into a problem that I don't understand. This program as is, should just accept a command line argument, load the file and display it to memory. However it displays it multiple times. I'm pretty sure the for loop is the problem, but it is the same technique as what is used in the programming reference I am using.
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
char* getFile( char* fileName ){
std::fstream inFile( fileName );
if( !inFile ) std::cout << "Could not open " << fileName << ".\n";
else{
inFile.seekg(0,inFile.end);
int len = inFile.tellg();
inFile.seekg(0,inFile.beg);
char* buffer = new char[len];
inFile.read( buffer, len);
inFile.close();
std::cout.write(buffer,len);
return buffer;
}
}
int main(int argc, char** argv){
if(argc != 2) std::cout << "Parameter required\n";
else{
std::string f = getFile( argv[1] );
for( size_t i = f.find( 0x0A, 0 ); i != std::string::npos ; i = f.find( 0x0A, i) ){
std::cout << f.substr(0,i)<<std::endl;
i++;
}
}
}
I see at least one of the problems with my code. I re-wrote the loop as a while loop because it was easier to follow and paid a little more attention to where I am starting and stopping. However it still seems to be printing twice.
int main(int argc, char** argv){
if(argc != 2) std::cout << "Parameter required\n";
else{
std::string f = getFile( argv[1] );
size_t start = 0;
size_t end = 1;
while( end != std::string::npos ){
end = f.find( 0x0A, start );
std::cout << f.substr(start,end)<<std::endl;
start = ( end + 1 );
}
This is because you have two printing statements that are displaying the contents of the file.
The first print statement is this one:
std::cout.write(buffer,len);
The second one is this:
std::cout << f.substr(0,i)<<std::endl;
I'm reading files in a directory and passing it to a function, I think I'm doing it in a wrong way, not able to figure out.
Here is my code first it reads files in a folder and send it to a function for further operations.
#include <dirent.h>
#include <stdio.h>
#include <vector>
#include <string>
#include <iostream>
using namespace std;
std::vector<std::string> fileName;
int main(void)
{
DIR *d;
struct dirent *dir;
vector<string> fileList;
int i=0;
d = opendir("files");
if (d)
{
while ((dir = readdir(d)) != NULL)
{
i++;
fileList.push_back(dir->d_name);
}
for(int i=0;i<fileList.size();i++) {
cout<<fileList[i]<<endl;
doSomething(fileList[i]);
}
closedir(d);
}
return(0);
}
int doSomething(fileName) {
//do something
}
Error
main.cpp: In function ‘int main()’:
main.cpp:29:28: error: ‘doSomething’ was not declared in this scope
doSomething(fileList[i]);
^
main.cpp: At global scope:
main.cpp:37:26: error: cannot convert ‘std::vector<std::basic_string<char> >’ to ‘int’ in initialization
int doSomething(fileName) {
^
main.cpp:37:28: error: expected ‘,’ or ‘;’ before ‘{’ token
int doSomething(fileName) {
^
Since your doSomething function is defined after main, it is not visible, that causes the first error. The correct way would be to at least declare the function first:
int doSomething(); //declaration
int main()
{
doSomething(); //now the function is declared
}
//definition
int doSomething()
{
}
Now, the second and third errors is emited because you didn't include the fileName parameter's type in your function definition. Based on your code, it should be a string:
int doSomething(string fileName)
{
}
I also noticed that, while this function returns int, you are not using it's returned value. Nevertheless, don't forget to return something from doSomething, otherwise it will cause undefined behavior.
Yes, Boost is great, but it's a bit bloaty. So, just for completenessapplied to reading images in a directory for OpenCV:
// you need these includes for the function
//#include <windows.h> // for windows systems
#include <dirent.h> // for linux systems
#include <sys/stat.h> // for linux systems
#include <algorithm> // std::sort
#include <opencv2/opencv.hpp>
#include <iostream> //cout
using namespace std;
/* Returns a list of files in a directory (except the ones that begin with a dot) */
int readFilenames(std::vector<string> &filenames, const string &directory)
{
#ifdef WINDOWS
HANDLE dir;
WIN32_FIND_DATA file_data;
if ((dir = FindFirstFile((directory + "/*").c_str(), &file_data)) == INVALID_HANDLE_VALUE)
return; /* No files found */
do {
const string file_name = file_data.cFileName;
const string full_file_name = directory + "/" + file_name;
const bool is_directory = (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
if (file_name[0] == '.')
continue;
if (is_directory)
continue;
filenames.push_back(full_file_name);
} while (FindNextFile(dir, &file_data));
FindClose(dir);
#else
DIR *dir;
class dirent *ent;
class stat st;
dir = opendir(directory.c_str());
while ((ent = readdir(dir)) != NULL) {
const string file_name = ent->d_name;
const string full_file_name = directory + "/" + file_name;
if (file_name[0] == '.')
continue;
if (stat(full_file_name.c_str(), &st) == -1)
continue;
const bool is_directory = (st.st_mode & S_IFDIR) != 0;
if (is_directory)
continue;
// filenames.push_back(full_file_name); // returns full path
filenames.push_back(file_name); // returns just filename
}
closedir(dir);
#endif
std::sort (filenames.begin(), filenames.end()); //optional, sort the filenames
return(filenames.size()); //Return how many we found
} // GetFilesInDirectory
void help(const char **argv) {
cout << "\n\n"
<< "Call:\n" << argv[0] << " <directory path>\n\n"
<< "Given a directory of images, create a vector of\n"
<< "their names, read and display them. Filter out\n"
<< "non-images\n"
<< endl;
}
int main( int argc, const char** argv )
{
if(argc != 2) {
cerr << "\nIncorrect number of parameters: " << argc << ", should be 2\n" << endl;
help(argv);
return -1;
}
string folder = argv[1];
cout << "Reading in directory " << folder << endl;
vector<string> filenames;
int num_files = readFilenames(filenames, folder);
cout << "Number of files = " << num_files << endl;
cv::namedWindow( "image", 1 );
for(size_t i = 0; i < filenames.size(); ++i)
{
cout << folder + filenames[i] << " #" << i << endl;
cv::Mat src = cv::imread(folder + filenames[i]);
if(!src.data) { //Protect against no file
cerr << folder + filenames[i] << ", file #" << i << ", is not an image" << endl;
continue;
}
cv::imshow("image", src);
cv::waitKey(250); //For fun, wait 250ms, or a quarter of a second, but you can put in "0" for no wait or -1 to wait for keypresses
/* do whatever you want with your images here */
}
}