I am sorry for the vague title. This question is a continuation of a previous question posted
here: Using a C++ class object in fortran 77 what I need to do is to reuse the objects created from C++ in Fortran.
The code that I am dealing with is a very simple Fortran code:
C23456
program main
C Pointers to C++ classes. Never use them!
C Just pass them to the C++ functions.
integer*4 shapeToMesh
integer*4 faceMap
integer*4 edgeMap
integer*4 vertexMap
C We have to append //CHAR(0) to the string since it must be
C Null terminated
call readstep('cube.stp'//CHAR(0),isuccess,shapeToMesh)
call createfacemap(shapeToMesh,faceMap)
end
Where the shapeToMesh is a class object that contains the geometry that is parsed from the
input step file. The faceMap edgeMap vertexMap are objects that assign a unique integer to each face edge and vertex respectively
Now the readstep or readstep_ (note that those are C++) function works good and here is the code:
//SuccessInt contains information about successful loading
//of file. 1 for success, 0 for failure
void readstep_(char* inputFile,int* successInt, TopoDS_Shape** shape){
//Print out the filename received from fortan for debug reasons
int len = strlen(inputFile);
std::cout << "Input file ";
for(int i=0; i<len; i++)
std::cout << inputFile[i];
std::cout << std::endl<< std::endl;
//This has a private contructor. So I must first declare
//and then call the constructor.
STEPControl_Reader reader;
reader = STEPControl_Reader();
int succeed = reader.ReadFile(inputFile);
if(!succeed){
std::cout << "There was an error with the input file" << std::endl;
(*successInt) = succeed;
return;
}
reader.NbRootsForTransfer();
reader.TransferRoots();
//Assign memory, then opject
*shape = new TopoDS_Shape();
**shape = reader.OneShape();
(*successInt) = succeed;
return;
}
As you may have already seen from my Fortran snippet, the next thing I want to do is to create a list of my faces present in the shape. To do this I call the createfacemap or createfacemap_ function the code of which is shown below:
void createfacemap_(TopoDS_Shape** shape, TopTools_IndexedMapOfShape** map){
TopoDS_Shape ashape = TopoDS_Shape();
ashape = (**shape);
if(ashape.IsNull())
std::cout << "Shape is null";
*map = new TopTools_IndexedMapOfShape();
TopExp::MapShapes(ashape,TopAbs_FACE,(**map));
std::cout << "Faces: " << (**map).Extent() << std::endl;
return;
}
But instead of 6 Faces I get a result of 0 faces. To investigate any further, I debugged the
program using a point. And the results can be seen in the screenshots
It can be seen that the map variable is initialized and some processing goes on since the
NbBuckets change, however the size does not change at all that means that there are no objects stored. I am using the openCASCADE library. Here are the relevant references:
http://dev.opencascade.org/doc/refman/html/class_topo_d_s___shape.html
http://dev.opencascade.org/doc/refman/html/class_top_exp.html
http://dev.opencascade.org/doc/refman/html/class_top_tools___indexed_map_of_shape.html
any help would be really appreciated!
Related
I made a class consuming a serialized Opencv matrix. It is working fine and the Matrix is deserialized. If I try to display it inside the method of the class using the imshow method, it will work perfectly well, displaying without error. However, I am passing a parameter reference to a Matrix pointer from my main function in order to further process this matrix. When I try to display it in the main, I end up with a segmentation fault.
The weird part is that if I try to display the matrix in both the class method and the Main, I will end up with two windows working fine (sometimes I will get a segmentation fault but most of the time it works good).
If I remove the displaying code from the method, I won't even be able to display one frame before getting a segmentation fault.
I have tried using a shared_ptr, passing a pointer to the pointer instead of a reference, or even simply returning the value.
My code is kind of messy but the main aim of it is testing.
Here is the code of the method :
void VideoConsumer::getVideoFrame(cv::Mat* &mat) {
Message msg = _consumer->poll();
mat = NULL;
if(!msg) {
cerr << "No message received" << endl;
return;
}
if(msg.get_error()) {
if(!msg.is_eof()) {
cerr << "[+] Received error notification: " << msg.get_error() << endl;
}
return;
}
Document document;
string jsonPayload = "";
for(auto i=msg.get_payload().begin(); i != msg.get_payload().end();i++) {
jsonPayload += *i;
}
document.Parse(jsonPayload.c_str());
if(document.HasMember("rows") && document.HasMember("cols") && document.HasMember("data")) {
int rows = document["rows"].GetInt();
int cols = document["cols"].GetInt();
int type = document["type"].GetInt();
string data = document["data"].GetString();
std::vector<BYTE> decodedBytes = base64_decode(data);
stringstream ss;
for(int i=0;i< decodedBytes.size(); i++) {
ss << decodedBytes[i];
}
string decoded_data = ss.str();
cout << "Constructed string" << endl;
mat = new cv::Mat(rows,cols,type,(void *)decoded_data.data());
/*cv::imshow("test",*mat);
while(cv::waitKey(10) != 27)*/ //This is where it is displayed
return;
} else {
return;
}
}
And the code in the main :
...
if(parser.has("stream")) {
VideoConsumer consumer("localhost:9092","video-stream-topic","testId2");
consumer.setConsumer();
while(1) {
Mat *frame = NULL;
consumer.getVideoFrame(frame);
if(frame == NULL) {
cout << "Null frame" << endl;
continue;
}
if(!frame->empty() && frame->rows > 0 && frame->cols > 0) {
imshow("Test",*frame);
waitKey(10);
frame->release();
}
}
}
I am completely out of ideas and have tried every single thing I knew or found on my researches.
EDIT : Added frame->release() in order to free the allocation, still same issue.
There is a problem in your matrix initialization... Specifically in here:
mat = new cv::Mat(rows,cols,type,(void *)decoded_data.data());
That one is this constructor
Mat (int rows, int cols, int type, void *data, size_t step=AUTO_STEP)
which in the documentation says the following about the *data parameter
data Pointer to the user data. Matrix constructors that take data and
step parameters do not allocate matrix data. Instead, they just
initialize the matrix header that points to the specified data, which
means that no data is copied. This operation is very efficient and can
be used to process external data using OpenCV functions. The external
data is not automatically deallocated, so you should take care of it.
This means that as soon it goes out of scope (the function exits) the string which you created (decoded_data) will exit and the data will be deallocated by the string, and then your cv::Mat will have a reference to a data that is not valid anymore...
You can always initialize the matrix with something like
cv::Mat(rows,cols,type)
and then use something like std::memcpy or similar to copy the data to the mat.data member. Actually, AFAIK it is not needed to pass byte to string and then to mat which is casted to void and then to uchar....
try something like:
mat = cv::Mat(rows,cols,type);
std::memcpy(&decodedBytes[0], mat.data, decodedBytes.size());
Just a small warning for this solution, you need to do a check that decodedBytes is not empty and that mat.data has enough space to receive all the contents of decodedBytes. To do this check just make sure:
// size in bytes to copy == size of the allocated data of mat in bytes
decodedBytes.size() == (mat.elemSize() * mat.rows * mat.cols)
A couple of remarks more that may not be an issue now, but may bite you later:
Do not use cv::Mat pointers... The behaviour of cv::Mat is already like a smart pointer.
Beware of the casting/copy of data from sign to unsign and viceversa :) I think now it is done correctly, but this may become a problem later.
I'm trying to code a counter for a class I made in c++.
I'm passing an amount of time, deltaT, to a method of the Wake class, which does simply adds it onto the value already stored by a variable in the class. The code is:
void checkPlayerWakes(int deltaT){
for(size_t i = 0; i < game.getPlayer().getWakes().size(); i++){
Wake& w = game.getPlayer().getWakes().at(i);
w.age(deltaT);
}
}
However, the timer which is meant to be increasing, is remaining at 0.
The code to change the timer is:
void Wake::age(int millis) {
cout << "Updating : " << currentLife;
this->currentLife += millis;
setAlpha(((double)currentLife)/((double)lifeTime));
cout << " " << currentLife << endl;
}
E.g.
first current life: 0
second current life: 16
I know that if I were to use
Wake w = something
w.age(deltaT)
it wouldn't work because "w" would just be a copy of the object. However, that's clearly NOT my problem here? Also game.getPlayer() also returns a reference, a PLAYERSHIP&.
Last time I had a similar problem, it was solved by calling and returning references instead of just the ClassName. Am I still doing something wrong?
getWakes() needs also to return a reference, and should return vector& as opposed to vector.
I'm adding this here to make sure that this question is marked as answered.
I am making fairly new to C++ and I am using it to make a text based game for a school project. However during the first section of the game the player answers questions by entering the number shown beside the answer they choose. However when I tested the variables the input going to using std::cout they return different values depending on where they are outputted. If I outputted them in the class I am using to set them (Introduction) the they return the correct value such as 1 or 3 etc. However when I output them in any file other than Introduction.cpp, the value displayed is -858993460 for all of the values. I get the same result from Main.cpp when I call them in my main function and if I call them from another function in a different class to Introduction.
This is an example of some of the code used to get input from the user:
void Introduction::CharacterCreation()
{
Universal universal;
std::fstream creation("Introduction_CharacterCreation.txt");
universal.line = 5;
for (int i = 0; i < universal.line; i++)
{
if (i > 0)
{
std::getline(creation, universal.displayText);
std::cout << universal.displayText << std::endl;
}
if (i == 4)
{
std::cout << std::endl;
std::cin >> universal.gender;
while (universal.gender <= 0 || universal.gender >= 3)
{
std::cout << "Please make a valid choice" << std::endl;
std::cin >> universal.gender;
}
}
}
// Code cut out here
}
The gender variable is an int declared in the Universal class, and the user is prompted to enter 1 for male or 2 for female by text pulled from a separate file. If the input is not 1 or 2 then a while loop forces the player to keep re-answering the question until they enter 1 or 2. The line variable is also an int however that is used for the for loops to ensure the right lines are read by the program.
To output the gender variable this is the code I use:
std::cout << gender << std::endl;
There is no universal. as it is being called within the Universal class itself.
This has confused me massively and I can't get my head around what is causing the problem. Any help or explanation would be great, thanks in advance.
Short answer: you're declaring a Universal object in your CharacterCreation() method. When this function exits since the scope of the universal variable was local so the entire object is destroyed.
Whatever you are outputting is just uninitialized garbage. It could really be any number depending on what system is compiling / running the program. To test this right after you input the gender, while still inside the function, try running
std::cout << universal.gender << std::endl;
This should output just fine.
There are a lot of ways you can go about fixing this. Since you didn't post where you call this method or your Universal class I can't say for sure. But I can speculate one such solution which is to declare the Universal object outside the method and then pass it in as a parameter:
Universal universal = Universal();
Introduction::CharacterCreation(universal);
std::cout << universal.gender << std::endl;
And just declare your function header to accept a Universal object:
void Introduction::CharacterCreation(Universal & universal)
{
//code here
}
In my attempt to load .OBJ-files I load vertex data into std::vectors to send them to the GPU later. I fill three vectors, for normals, vertices and texture coordinates. The size of the normal vector is far higher than the size of the other two vectors, even if its filled with the same number of elements.
Code:
SceneTree* generateSceneTree(OBJScene* scene){
PostProcessing::triangulateFaces(scene);
SceneNode* node = new SceneNode;
vector<Vec<3>>& sceneNormals = scene->attributeData[Attribute::Normal];
vector<Vec<3>>& sceneVertices = scene->attributeData[Attribute::Position];
vector<Vec<3>>& sceneTexCoords = scene->attributeData[Attribute::TexCoord];
map<string,MaterialInfo*> mtls;
for(string s : scene->mtlLibs){
auto temp = loadMTL(s);
mtls.insert(temp.begin(),temp.end());
}
vector<Vec<3>> meshNormals; <-- creating vectors here.
vector<Vec<3>> meshVertices;
vector<Vec<2>> meshTexCoords;
for(auto g : scene->groups){
meshNormals.clear();
meshNormals.reserve(g.faces.size()*3);
meshVertices.clear();
meshVertices.reserve(g.faces.size()*3);
meshTexCoords.clear();
meshTexCoords.reserve(g.faces.size()*3);
AABB bBox;
cout << "num of faces: " << g.faces.size() << endl;
for(auto f : g.faces){
for(auto p : f.points){
uint vIndex = p.indices[Attribute::Position];
uint nIndex = p.indices[Attribute::Normal];
uint tIndex = p.indices[Attribute::TexCoord];
Vec<3> n = sceneNormals.at(nIndex);
Vec<3> v = sceneVertices.at(vIndex);
Vec<3> t = sceneTexCoords.at(tIndex);
meshNormals.push_back(n);
meshVertices.push_back(v);
meshTexCoords.push_back(t.toVec<2>());
bBox += meshVertices.back();
}
}
cout << "meshNormals size: " << meshNormals.size() << endl;
cout << "meshVertices size: " << meshVertices.size() << endl;
cout << "meshTexCoords size: " << meshTexCoords.size() << endl;
Mesh* m = new Mesh({
{meshVertices,Attribute::Position},
{meshNormals,Attribute::Normal},
{meshTexCoords,Attribute::TexCoord}
},GL_TRIANGLES);
SceneLeaf* leaf = new SceneLeaf;
leaf->nodeData = {Matrix4(),bBox};
leaf->leafData = {m, mtls[g.mtlName]};
node->addChild(leaf);
}
return node;
}
Output:
num of faces: 1087474
meshNormals size: 2958875950
meshVertices size: 3262422
meshTexCoords size: 3262422
This seems highly illogical. The program crashs afterwards with a std::bad_array_new_length exception because the Mesh class cant create an array of size 2958875950 to send to the GPU.
Update:
If I swap the declarations of meshVertices and meshNormals, meshVertices has the wrong size. So the first created vector is affected.
If I use std::list instead of std::vector, everything works.
If I comment out the ....reserve(g.faces.size()*3); lines, a std::bad_alloc is thrown.
My guess is that you have a memory corruption bug "somewhere" that is overwriting the meshNormals variable on the stack. The fact that swapping the meshNormals and meshVertices declarations leads to meshVertices becoming bad matches that theory.
To narrow in on the problem you can do a few things:
Comment out all lines in the inner for(auto p : f.points) loop and see if the error still occurs.
Assuming it doesn't, start uncommenting lines one-by-one until the error shows up again.
Try making a minimal, stand-alone test code example that duplicates the problem (it would help immensely if you did this before posting a SO question).
The simple answer is that your pointers at the start are pointing to somewhere else, either:
You are casting the "scene" structure.
You have junk or unset pointer in the scene structure for normal vector. Could be that you put junk there far before entring the function.
You did notice the 2958875950 is junk/negative integer?
In my program I need to copy (or even use) a private data structure into the .cpp file of a completely different class. At the moment I am even having trouble just simply accessing it remotely, it seg faults when I try to print it. Here is a simplified version of my class with the data structure:
class Graph
{
private:
class Edge
{
public:
Edge(string vertex, int weight)
{
m_vertex = vertex;
m_weight = weight;
}
~Edge(){}
string m_vertex;
int m_weight;
};
vector< list<Edge> > adjList;
public:
Graph();
~Graph();
vector < list < Edge > > get_adjList(){return adjList;}
//Other functions....
};
In a completely different function I try to do this...
void MinPriority::testPrint(string targetVertex) //FOR TESTING PURPOSES SO FAR (FAILS TO WORK) SEGMENTATION FAULT NO MATTER WHAT
{
targetVertex = "A";
Graph graph;
graph.adjList = graph.get_adjList(); //adjList is our empty container based on the array of linked lists
/*1*/cout << graph.get_adjList()[0].front().m_vertex << " TEST!" << endl;
/*2*/cout << "The very first vertex is: ";
if(graph.adjList.size() == 0)
cout << "NULL<!>" << endl;
else cout << graph.adjList[0].front().m_vertex << endl;
}
Note i set targetVertex to 'a' so my program compiles since im including -Werror in my makefile (required for assignment).When I comment out /*1*/ and run down to /*2*/ the output will always be "The very first vertex is: NULL<!>", no matter how many elements are in the data structure. At /*1*/ I try to print out the object returned by the function get_adjList() but it seg faults reading this:
Exception: STATUS_ACCESS_VIOLATION at eip=611298C5
eax=0A0A0A0A ebx=01010101 ecx=20050884 edx=F5F5F5F5 esi=20058488 edi=20060000
ebp=0028A8D8 esp=0028A8D0 program=C:\cygwin\home\Ryan\311\P5Dec16\Graph.exe, pid 5612, thread main
cs=0023 ds=002B es=002B fs=0053 gs=002B ss=002B
Stack trace:
Frame Function Args
0028A8D8 611298C5 (20058400, 0000000A, 20058488, 610FD3CA)
0028A938 6115F91F (0028D41C, 61187720, 0028A958, 0043455D)
0028A988 61137BF7 (0028D41C, 20058400, 00000001, 20058488)
0028A9B8 61137CD5 (20058400, 00000001, 20058488, 61187720)
0028A9D8 610D6745 (00449240, 20058400, 20058488, 004493C4)
0028AA68 004439BA (004493C0, 6123D5FC, 004452B4, 0028AAA0)
0028AB08 00402756 (0028AC20, 0028ABB0, 20010100, 004011C1)
0028AC68 00401583 (00000001, 0028AC90, 20010100, 612757A2)
0028ACF8 6100763A (00000000, 0028CD78, 61006C50, 00000000)
End of stack trace
Segmentation fault (core dumped)
Basically in short, I would like to know what this stack trace is (I have had seg faults before but I have never seen this). I would like to know how to properly access the data structure from class Graph in other files that #include "Graph.h". I am also unsure how to copy my object inside of testPrint();. Why is it that this works perfectly in Graph.cpp?
void Graph::set_array(string vertex)
{
//increment vector size by 1 and insert a new Edge object into the vector of linked lists
cout << "ADDING " << vertex << " TO VECTOR" << endl;
adjList.resize(adjList.size() + 1);
adjList[adjList.size() - 1].push_back(Edge(vertex, 0));
}
Graph graph;
As you stated, the default constructor of Graph does nothing. So at this point, graph.adjList is empty.
graph.adjList = graph.get_adjList();
This is a pointless statement which assigns to graph.adjList from a copy of itself. Since it was empty before, it is still empty now.
cout << graph.get_adjList()[0].front().m_vertex << " TEST!" << endl;
This tries to access the first element of (a copy of) graph.adjList. But graph.adjList is empty (i.e. it doesn't have a first element), so this is undefined behavior. It may or may not be the cause of your segfault, but it is certainly a problem that must be fixed before any further useful debugging can take place.