So I'm trying to write a shader class in C++ similar to this. This is my file structure:
| -- /source
| | -- main.cpp
| | -- /Shaders
| | | -- Shader.h
| | | -- shader.frag
| | | -- shader.vert
In my main.cpp file, I import shaders.h. Shaders.h constains the shader class, which reads in shader code from the shader.frag and shader.vert files (or so it should). The path I pass from main.cpp is Shaders/shader.frag and Shaders/shader.vert, and I am getting the error No such file or directory.
Here is my (or their) relevant shader code:
#ifndef SHADER_H
#define SHADER_H
#include <glad/glad.h>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
Shader(const char* vertexPath, const char* fragmentPath)
{
// 1. retrieve the vertex/fragment source code from filePath
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
// ensure ifstream objects can throw exceptions:
vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try
{
// open files
vShaderFile.open(vertexPath); <------- this is where it is getting caught
fShaderFile.open(fragmentPath); <---------- and i assume it would be here as well
std::stringstream vShaderStream, fShaderStream;
// read file's buffer contents into streams
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
// close file handlers
vShaderFile.close();
fShaderFile.close();
// convert stream into string
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch (std::ifstream::failure e)
{
char buffer[256];
strerror_s(buffer, 256, errno);
printf("ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ: %s\n", buffer);
}
...
I have tried multiple different path variations. I've tried passing an absolute path as well, and consistently get the same error. I would really appreciate any help with this.
You just need to include the <fstream> library.
Related
I try to use Assimp::Importer.ReadFile() to load my obj.file but it turns out that assimp fail to find the file correctly.
Here is a simple test
#include<string>
#include<assimp/scene.h>
#include <assimp/Importer.hpp>
#include <assimp/postprocess.h>
using namespace std;
int main(){
Assimp::Importer importer;
string modelPath = "D:\\素材\\nanosuit\\nanosuit.obj";
const aiScene* scene = importer.ReadFile(modelPath, aiProcess_Triangulate | aiProcess_FlipUVs );
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
cout << "ERROR::ASSIMP::" << importer.GetErrorString() << endl;
}
else cout << scene;
and the output is following text
ERROR::ASSIMP::Unable to open file "D:\素材\nanosuit\nanosuit.obj".
I haved tried to load different obj.file and it doesn't work too
This is a problem with the unicode name. You need to use a workaround to fix this. Use the Wi32-API-Call
SetCurrentDirectory(L"D:\\素材\\nanosuit\\");
to open the folder and import the asset afterwards:
const aiScene* scene = importer.ReadFile(L"nanosuit.obj", aiProcess_Triangulate | aiProcess_FlipUVs );
There is a design error in the Asset-Importer-Lib. The imported name will be used to name the asset and the asset-name is using ASCII. So unicode names will interpreted as ASCII-names and this will cause your error.
I'm trying to map a region of a particular size into the memory, looking at the docs example:
https://www.boost.org/doc/libs/1_70_0/doc/html/interprocess/sharedmemorybetweenprocesses.html#interprocess.sharedmemorybetweenprocesses.mapped_file
as you can notice, boost version is 1.70.0
using namespace boost::interprocess;
const char *FileName = "c_e_d.bin";
const std::size_t FileSize = 10000;
file_mapping::remove(FileName);
std::filebuf fbuf;
auto p = fbuf.open(FileName, std::ios_base::in | std::ios_base::out
| std::ios_base::trunc | std::ios_base::binary);
//Set the size
auto r = fbuf.pubseekoff(FileSize-1, std::ios_base::beg);
auto r2 = fbuf.sputc(0);
//Create a file mapping
file_mapping m_file(FileName, read_write);
//Map the whole file with read-write permissions in this process
mapped_region region(m_file, read_write);
but an exception occurs:
I don't need the parent-child functionality, just many threads writing directly to a mmaped region of memory.
Can somebody help me solve this out please?
Thank you in advance.
Additional debug info:
p is created seemed to be:
It is also seemed to be that the two following operations did work:
Your fbuf doesn't sync. Either sync or limit the scope to get implicit sync on destruction.
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <fstream>
namespace bip = boost::interprocess;
int main()
{
const char* FileName = "c_e_d.bin";
const std::size_t FileSize = 10000;
bip::file_mapping::remove(FileName);
{
std::filebuf fbuf;
/*auto p =*/fbuf.open(FileName,
std::ios_base::in | std::ios_base::out |
std::ios_base::trunc |
std::ios_base::binary);
// Set the size
fbuf.pubseekoff(FileSize - 1, std::ios_base::beg);
fbuf.sputc(0);
fbuf.pubsync();
}
// Create a file mapping
bip::file_mapping m_file(FileName, bip::read_write);
// Map the whole file with read-write permissions in this process
bip::mapped_region region(m_file, bip::read_write);
}
In my program I am copying an executable file from one location to another, and then execute the copied file. When the copied file is executed I get a "permission denied" error. But if I restart my program then the file gets executed without a problem. Can someone please help me with the problem? The code below is simple, but demonstrates the problem.
void copyFile(string _from, string _to)
{
std::ifstream src(_from.c_str());
std::ofstream dst(_to.c_str());
dst << src.rdbuf();
}
int main()
{
string original("./exe_file");
string dest_file("./exe_dir/exefile");
system("./exe_dir/exefile"); //Fails on first run because exe_dir does not exist.
//mkdir and copy the file.
mkdir("./exe_dir",S_IRWXO | S_IRWXU | S_IRWXG);
copyFile(original, dest_file);
//Open the file and close it again to flush the attribute cache.
int fd = open(dest_file.c_str(),O_RDONLY);
close(fd);
//The line below fails with system error code 2 (Permission denied) on exefile.
return system("./exe_dir/exefile");
{
I used 'chmod 777 exe_file' on the original file before executing the program, and after running this program the destination also has the same access rights. I can execute it manually just fine. And every subsequent run of the program is successful. Why does it fail on the first run?
You should close file you've created.
See cplusplus.com: std::ifstream::close
Coderz, no idea what problems you are experiencing with your IDE but this works fine for me.
#include <iostream>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cstdlib>
using namespace std;
void copyFile(string _from, string _to)
{
std::ifstream src(_from.c_str());
std::ofstream dst(_to.c_str());
dst << src.rdbuf();
}
int main()
{
string original("./exe_file");
string dest_file("./exe_dir/exefile");
system("./exe_dir/exefile");
if (mkdir("./exe_dir", S_IRWXO | S_IRWXU | S_IRWXG))
perror("mkdir");
copyFile(original, dest_file);
if (chmod("./exe_dir/exefile", S_IRWXU | S_IRWXG | S_IRWXO) == -1)
perror("chmod");
return system("./exe_dir/exefile");
}
Note that exe_file is a simple Hello World binary and the results are
sh: 1: ./exe_dir/exefile: not found
Hello World
where the copied file is
-rwxrwxrwx 1 duck duck 18969 May 9 19:51 exefile
within directory
drwxrwxr-x 2 duck duck 4096 May 9 19:51 exe_dir
I'm having some trouble writing a Linux console app which reads apache logs.
I need to handle bash script arguments, the last one being a path to the log file.
My problem is that if the file doesn't exist, I would like to throw an exception.
But when I try to open the file in read-only mode, instead of failing it creates the file !
Here's the code :
// logreader.h
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <stdexcept>
class LogReader
{
public:
LogReader(int, const char **);
virtual ~LogReader();
// ...
private:
std::ifstream log_;
};
// logreader.cpp
#include <logreader.h>
LogReader::LogReader(int argc, const char ** argv):
log_()
{
log_.exceptions(std::ifstream::failbit | std::ifstream::badbit);
for (int i = 1; i < argc; ++i)
{
std::string arg(argv[i]);
if (i == argc - 1)
{
try
{
log_.open(arg.c_str(), std::ifstream::in);
}
catch (std::ifstream::failure)
{
throw std::runtime_error("The file " + arg + " wasn't opened");
}
}
}
}
LogReader::~LogReader()
{
}
// main.cpp
#include <logreader.h>
int main(int argc, const char ** argv)
{
LogReader(argc, argv);
return 0;
}
Script call:
jmcomets $ ./test -g -l
jmcomets $ ls -l
-rw-rw-r-- 1 jmcomets jmcomets 0 Nov 14 22:41 -l
Since you are opening an std::ifstream it is necessary to add std::ios_base::in (or any other spelling of the std::ios_base::openmode) according to 27.9.1.9 [ifstream.members] paragraph 4: The flag is automatically added by the call to open(). Note that an std::ofstream or an std::fstream would automatically add std::ios_base::out (27.9.1.13 [ofstream.members] paragrpah 3) or std::ios_base::in | std::ios_base::out (27.9.1.17 [fstream.members] paragraph 3), both of which resulting in a new file being created if it doesn't exist (and there are write permissions, etc.).
If the code you posted creates a new file, the implementation of the standard C++ library is wrong: when only the flag std::ios_base::in is specified, the file is open "as if" using the open mode "r" with fopen() (27.9.1.4 [filebuf.members] paragraph 5). fopen() in turn doesn't create a new file when it gets an open mode of "r" (7.21.5.3 paragraph 3).
You can set the failbit in the exceptions flag for the ifstream:
std::ifstream log;
log.exceptions ( std::ifstream::failbit );
try {
log.open ("test.txt");
}
catch (std::ifstream::failure e) {
std::cout << "Exception opening/reading file\n";
}
Source
I've tested, and ifstream will throw a failure exception if the file cannot be opened, e.g. file not found, no read permissions. It will open read-only.
You need to specify ifstream::in as a second parameter as:
log.open(arg.c_str(), ifstream::in)
You can also do:
std::ifstream log(arg.c_str(), ifstream::in);
and skip the call to open()
Edit with something Linux compatible;
Try opening with fopen before writing. If the file DNE the FILE pointer will be null.
FILE * file;
file = fopen ("myfile.txt","r");
if (file == NULL)
//throw if fopen didn't already.
else
//do stuff with my file
I'm trying to convert the following bash code into C++ using boost::iostreams:
#!/usr/bin/bash
(
gzip -cd file1.ext.gz
cat file2.ext
) | grep '^regex' # or sed 's/search/replace/'
I can open a file and decompress it:
std::ifstream s("file.ext.gz", std::ios_base::in | std::ios_base::binary);
boost::iostreams::filtering_istreambuf in;
in.push(boost::iostreams::gzip_decompressor());
in.push(s);
Then open an uncompressed file:
std::ifstream s2("file.ext", std::ios_base::in | std::ios_base::binary);
Now I'm a bit stuck, so here are my questions:
1) What's the boost::iostreams solution to concat the two streams?
2) How to output the result through a regex filter to emulate grep/sed?
As a result I'd like to have a an istream that i can copy to cout:
boost::iostream::copy(result, std::cout);
UPDATE complete solution using Hamigaki's concatenate:
/*
* convert the following bash script into C++
*
* #!/bin/bash
* (
* gzip -cd file1.ext.gz
* cat file2.ext
* ) | grep '^filter' | 'sed s/search/replace/g'
*
*/
#include <iostream>
#include <boost/bind.hpp>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filter/regex.hpp>
#include <boost/iostreams/filter/grep.hpp>
#include <boost/iostreams/copy.hpp>
// http://hamigaki.sourceforge.jp/hamigaki/iostreams/concatenate.hpp
#include "concatenate.hpp"
namespace io = boost::iostreams;
int main(int argc, char const* argv[])
{
io::file_source file1("file1.ext.gz");
io::file_source file2("file2.ext");
io::gzip_decompressor gzip;
io::regex_filter sed(boost::regex("search"), "replace");
io::grep_filter grep(boost::regex("^filter"));
io::filtering_istreambuf in1(gzip | file1);
io::filtering_istreambuf in2(file2);
io::filtering_istreambuf combined(sed | grep |
hamigaki::iostreams::concatenate(
boost::ref(in1),
boost::ref(in2)
)
);
io::copy(combined, std::cout);
return 0;
}
1) I don't know if there's anything built into boost, but this class seems to be exactly what you want: http://hamigaki.sourceforge.jp/hamigaki/iostreams/concatenate.hpp
The catch here is that it expects CopyConstructible devices to concatenate and Chains seem to not be CopyConstructible. However, we can easily work around that using boost::ref. This code does (almost) what I understood you're asking:
int main(int argc, char const* argv[])
{
boost::iostreams::filtering_istreambuf in;
boost::regex regex("search");
boost::iostreams::regex_filter rf(regex, "replace");
in.push(rf);
boost::iostreams::file_source file1(argv[1]);
in.push(file1);
boost::iostreams::file_source file2(argv[2]);
boost::iostreams::copy(hamigaki::iostreams::concatenate(boost::ref(in), file2), std::cout);
return 0;
}
I just used the regex filter instead of gzip, for testing.
2) boost::iostreams has a regex filter: http://www.boost.org/doc/libs/1_45_0/libs/iostreams/doc/classes/regex_filter.html
EDIT: You seem to have this working, now.
1) Not available in boost
Hamigakis's concatenate sounds interesting, but I couldn't figure out how to use it to combine two boost::iostreams::chains. The code mentions it's meant for "concatenation of devices", so it might not be usable for chains. Please correct me if I'm wrong.
EDIT: updated my question with the complete solution.
2a) grep behavior (filter):
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/filter/grep.hpp>
boost::iostreams::filtering_istreambuf in;
boost::regex regex("^search")
boost::iostreams::grep_filter grep(regex);
in.push(grep);
2b) sed behavior (search/replace):
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/filter/regex.hpp>
struct formatter {
std::string operator()(const boost::match_results<const char*>& match)
{
return str(boost::format("%s | %s") % match[2] % match[1]);
}
};
boost::iostreams::filtering_istreambuf in;
boost::regex regex("^([a-z]+) ([0-9]+)");
boost::iostreams::regex_filter sed(regex, formatter());
in.push(sed);