Pointer class variable returns NULL from muncion - c++

I'm developing a DLL (in Visual Studio 2013) to read TIFF (satellite images), using GDAL library, and having an issue to get back my variable with data - currently it empty (returns NULL).
In my DLL I have my funcion defined in the "RasterFuncs.h" like this:
namespace RasterFuncs
{
// This class is exported from the RasterFuncs.dll
class MyRasterFuncs
{
public:
// Open a raster file
static RASTERFUNCS_API int Open(char* rname, GDALDataset *poDataset);
};
}
and in my DLL cpp I have the following:
namespace RasterFuncs
{
int MyRasterFuncs::Open(char* rname, GDALDataset *poDataset)
{
poDataset = (GDALDataset *) GDALOpen(rname, GA_ReadOnly);
if (poDataset != NULL)
{
cout << "RasterXSize 1:" << poDataset->GetRasterXSize() << endl;
cout << "RasterYSize 1:" << poDataset->GetRasterYSize() << endl;
cout << "RasterCount 1:" << poDataset->GetRasterCount() << endl;
}
return 0;
}
}
at this point I have the poDataset with all image data.
However, I call this DLL form another CPP using the following code:
rfileName = "C:/Image1.tif";
// Open raster satelitte image
GDALDataset *poDataset = NULL;
GDALAllRegister();
RasterFuncs::MyRasterFuncs::Open(rfileName, poDataset);
if (poDataset != NULL)
{
cout << "RasterXSize:" << poDataset->GetRasterXSize() << endl;
cout << "RasterYSize:" << poDataset->GetRasterYSize() << endl;
cout << "RasterCount:" << poDataset->GetRasterCount() << endl;
}
and when I test poDataset that come back, shows NULL.
Anybody could help in this issue?
Thanks in advance and best regards!

Remember that by default arguments to functions are passed by value, meaning the function have a copy of the value.
When you assign to the poDataset variable in the function, you're only changing your local copy. The calling function will not see this modification. You need to pass the argument by reference:
static RASTERFUNCS_API int Open(char* rname, GDALDataset*& poDataset);

Joachim is spot on, but on the flip side you could pass a pointer to the pointer rather than a reference to the pointer. I won't go into the pointers vs references battle, as both are good to know and understand.
static RASTERFUNCS_API int Open(char* rname, GDALDataset **poDataset);
and
RasterFuncs::MyRasterFuncs::Open(rfileName, &poDataset);
("**" means "pointer to a pointer" and "&" means "address of")

Related

object empty inside calling function using pointer as argument

I am learning C++ with pointers and trying to program a small game. I have a class PlayerManager which should create players and save them in a file.
The code compiles but when I call the method savePlayer, the pointer inside the method is valid but I cannot access the object to which the pointer is pointing.
I have searched for similar problems on internet but did not find anything similar. I may not be looking for the right keywords as I have no idea where this comes from.
I checked before the function is called and the pointer is working and I can access the object.
Inside the calling function, the pointer still has the right address but I cannot access the object. Nothing is returned.
After the calling function the pointer is still valid and the object accessible. (see //Comments in the code below)
Here are my two functions inside my PlayerManager class.
void PlayerManager::createPlayer()
{
Player *playerPtr = new Player();
std::string name;
std::cout << "Name: ";
std::cin >> name; // I entered for instance John
std::cout << std::endl;
playerPtr->setName(name);
std::cout << "PlayerPtr name before savePlayer: " << playerPtr->getName() << std::endl; // Outputs John
std::cout << "playerPtr before savePlayer: " << playerPtr << std::endl; // Ouputs the address
this->savePlayer(playerPtr);
std::cout << "PlayerPtr name after savePlayer but inside createPlayer: " << playerPtr->getName() << std::endl; // Outputs: John
delete playerPtr;
}
void PlayerManager::savePlayer(Player* playerPtr) // the called method
{
std::cout << "playerPtr inside savePlayer: " << playerPtr << std::endl; // Outputs the address
std::cout << "PlayerPtr name inside savePlayer: " << playerPtr->getName() << std::endl; // Outputs nothing
std::string const fileName = "Players/"+playerPtr->getName()+".txt";
std::cout << fileName << std::endl; // Outputs Players/.txt
std::ofstream myFile = std::ofstream(fileName.c_str());
if(myFile)
{
std::cout << "Enregistrement du nouveau joueur." << std::endl; // The code launches but no file is created.
myFile << "{"<< std::endl;
myFile << "name: " + playerPtr->getName() <<std::endl;
} else {
std::cout << "Erreur d'enregistrement du fichier." << std::endl;
}
}
I would like to be able to access the object created in createPlayer method inside the savePlayer method by passing a pointer but I just get an empty string for
playerPtr->getName()
I don't understand how the object is accessible before the call of the method and after but not inside as the address is still valid.
EDIT1
Thank you for guiding me to the obvious mistake !
Because of recuring crash of code:blocks my getName() method was deleted before I could save it and I did not think about checking it. By writing the following getName() it worked:
std::string Player::getName() const
{
return m_name;
}
Yet I do not understand why and How I got an output in createPlayer() although the method getName() was empty. Is this normal ?
EDIT 2
I'll create a new question for this strange behavior.
The code you have should work fine. My only guess is that there's something fishy about your getter function getName().
I presume you have something along these lines?
const std::string &getName() const
{
return name;
}
Online code example: https://rextester.com/INHG32142

Calling strings as functions in C++

I'm writing a 'skeleton' front-end in native C++ for other users where the users are creating functions that I will 'call' depending on arguments that are passed in. For example:
skeleton.exe /foo param1
would be used to call the function "int doFoo(param1){return 0;}" inside my skeleton. As more team members write functions, I would need to add those functions as well.
A stray thought I had - and I'm not even certain if this would be possible - would be to have a resource file - or, maybe, a resource xml file - that would list the command line arguments, the number of parameters and then the function I need to call for that parameter. So my resource file for the above would look like:
foo 1 doFoo
This way, as people create their functions, all they have to do is add it to the resource file.
The problem I am running into - and what I'm wondering if it is even possible - is whether I can 'interpret' that 'doFoo' as a function if it is read from the resource file. Is there anything that would allow me to 'interpret' a string as a function I can call?
You will need to map strings to function pointers.
One method is to create a lookup table another is to use std::map.
Search the internet for "c++ dispatch" and maybe "c++ double dispatch".
I think I've got it! I just need to ensure that each added function is declared with extern "C" __declspec(dllexport)! Example:
extern "C" __declspec(dllexport) int square(int x)
{
return (x*x);
}
typedef int(__cdecl *MYPROC)(int);
int _tmain(int argc, _TCHAR* argv[])
{
LPCSTR funcName = "square";
HMODULE hMod = GetModuleHandle(NULL);
if (hMod != NULL)
{
cout << "hMod is not NULL!" << endl;
MYPROC abstractSquare = (MYPROC)GetProcAddress(hMod, funcName);
if (NULL != abstractSquare)
{
cout << "abstractSquare is not NULL!" << endl;
int y = (abstractSquare)(10);
cout << "y = " << y << "!" << endl;
}
else
{
cout << "abstractSquare is NULL!" << endl;
}
}
else
{
cout << "hMod is NULL!" << endl;
}
return 0;
}

why can't I access imagedata in main?

I am trying to write a programme to read MRI data by using VTK and C++. But I can't get spacing of MRI raw data in main.
The "GetSpacing" only works in "ReadImageData" function. I think I made some mistake in C++ programming. But I don't know where it is.
vtkImageData* ReadImageData(string mri_imagedata_file)
{
vtkSmartPointer<vtkMetaImageReader> reader =
vtkSmartPointer<vtkMetaImageReader>::New();
reader->SetFileName(mri_imagedata_file.c_str());
reader->Update();
vtkImageData* metaimage = reader->GetOutput();
double sp[3];
metaimage->GetSpacing(sp);
cout << sp[0] << " " << sp[1] << " " << sp[2] <<endl; //<----------It works here.
return metaimage;
}
int main (int argc, char *argv[])
{
if(argc != 2)
{
cerr << "Usage: " << argv[0] << " MRI image data" <<endl;
return EXIT_FAILURE;
}
string mri_imagedata_file = argv[1];// Input "prost00.mhd"
vtkImageData* metaimage = ReadImageData(mri_imagedata_file);
double sp2[3];
metaimage->GetSpacing(sp2);
cout << sp2[0] << " " << sp2[1] << " " << sp2[2] << endl; //<-----It doesn't work here
}
Thank you for your attention.
Assuming vtkSmartPointer<vtkMetaImageReader> is a kind of smart pointer whatever, reader points to in the function is destructed when ReadImageData returns. That includes what metaimage is pointing to.
return metaimage;
// reader->~(); // Destructed here. Including what is pointed to by metaimage.
}
A good solution would be to return the smart pointer instead of metaimage. That way what is pointed to by reader will not be destructed when ReadImageData returns and will be available in main.
My assumption is that vtkMetaImageReader::GetOutput() returns pointer to some vtkMetaImageReader internal data, so when you exit ReadImageData your reader is destroyed and the pointer you return becomes invalid.
It looks like you forgot to pass the array as a parameter to GetSpacing in main, so it calls the overload that returns a double*, leaving your array untouched.
You're also printing an array called spacing although it looks like you want the spacing in sp2.

What is the meaning of "*&" in C++ [duplicate]

This question already has answers here:
Function argument type followed by *&
(3 answers)
Closed 9 years ago.
I was looking at manual of ACE framework and came across this declaration
int ACE_Stream<>::get (ACE_Message_Block *& mb, ACE_Time_Value * timeout = 0)
I'm not able to understand what *& stands for. I know * is for pointer and & is reference. Can any one explain what is the meaning of this declaration.
Thanks in advance
So as #NPE said *& makes changes to pointer propagate back. But to understand I just wrote down some code sharing it so that it can help others understand this correctly
#include <iostream>
using namespace std;
class DoSomething
{
public:
int n;
DoSomething(int i){
n = i;
}
virtual ~DoSomething();
};
DoSomething::~DoSomething()
{
}
int dosomething(DoSomething * a)
{
cout << "Got value from caller: (in dosomething) = " << a << endl;
a = new DoSomething(25);
return 0;
}
int dosomethingElse(DoSomething *& a)
{
cout << "Got value from caller: (in dosomethingElse) = " << a << endl;
a = new DoSomething(15);
return 0;
}
int main(int argc, char *argv[])
{
DoSomething *d = new DoSomething(10);
cout << "Pointer to DoSomething: " << d << endl;
dosomething(d);
cout << "After dosomething value of d: " << d << endl << endl;
dosomethingElse(d);
cout << "After dosomethingElse value of d: " << d << endl << endl;
delete d;
return 0;
}
So as #NPE said here is out put of this
Pointer to DoSomething: 0x955f008
Got value from caller: (in dosomething) = 0x955f008
After dosomething value of d: 0x955f008
Got value from caller: (in dosomethingElse) = 0x955f008
After dosomethingElse value of d: 0x955f028
So indeed if I create a new instance inside function it will propagate only if I use *& and not just *
Thank you to every one for the answers.
I know * is for pointer and & is reference.
Correct. So what you have here is a pointer, passed by reference.
mb is a pointer that's being passed by reference. This means that if get() were to change the value of the pointer, the change would propagate back to the caller.

Unexpected Non-NULL return

I am playing with TagLib (on Windows, built with MingW). I am trying to get TagLib to recognize when there is no ID3v1 or ID3v2 information in an MP3 file. According to the TagLib documentation, the ID3v2Tag() function in an MPEG File object should return a NULL pointer when there is no ID3v2 information in the file.
Unfortunately, this is not occurring. I have some test MP3 files I have made that I use in my code (I have made the files available):
blank.mp3 (download), no ID3v1 or ID3v2 information at all. I can confirm this by doing a plain text search for "TAG" and "ID3" in the files binary content.
only_album_id3v2.mp3 (download), has ID3v2 information (only the album is set)
only_album_id3v1.mp3 (download), has ID3v1 information (only the album is set)
Here is my code.
#include <iostream>
#include <mpeg/mpegfile.h>
#include <mpeg/id3v2/id3v2tag.h>
using namespace std;
int main()
{
cout << "Test." << endl;
TagLib::MPEG::File a("tests/other/blank.mp3");
TagLib::MPEG::File b("tests/id3v2/only_album_id3v2.mp3");
TagLib::MPEG::File c("tests/id3v1/only_album_id3v1.mp3");
TagLib::ID3v2::Tag * at = a.ID3v2Tag();
TagLib::ID3v2::Tag * bt = b.ID3v2Tag();
TagLib::ID3v2::Tag * ct = c.ID3v2Tag();
cout << at->album() << endl;
cout << bt->album() << endl;
cout << ct->album() << endl;
cout << "The program is done.";
return 0;
}
Running this program should break, due to a NULL pointer error on cout << at->album() << endl;, but it runs just fine. Also, when I cout << ct << endl;, it returns a memory address.
Here is the output:
Test.
test album id3v2
The program is done.
EDIT:
Here is a new test.
#include <iostream>
#include <mpeg/mpegfile.h>
#include <mpeg/id3v2/id3v2tag.h>
using namespace std;
int main()
{
cout << "Test." << endl;
TagLib::MPEG::File a("tests/other/blank.mp3");
TagLib::MPEG::File b("tests/id3v2/only_album_id3v2.mp3");
TagLib::MPEG::File c("tests/id3v1/only_album_id3v1.mp3");
TagLib::ID3v2::Tag * at = a.ID3v2Tag();
TagLib::ID3v2::Tag * bt = b.ID3v2Tag();
TagLib::ID3v2::Tag * ct = c.ID3v2Tag();
if(at == NULL)
{
cout << "at is NULL.";
}
else
{
cout << "at is not NULL.";
}
cout << endl;
if(bt == NULL)
{
cout << "bt is NULL.";
}
else
{
cout << "bt is not NULL.";
}
cout << endl;
if(ct == NULL)
{
cout << "ct is NULL.";
}
else
{
cout << "ct is not NULL.";
}
cout << endl;
cout << "The program is done.";
return 0;
}
And here is the output.
Test.
at is not NULL.
bt is not NULL.
ct is not NULL.
The program is done.
I examined TagLib's code briefly.
I know nothing about it and never used it, but the code looks buggy to me. Here's why -
In MPEG::File::read(), we are looking for a tag - d->ID3v2Location = findID3v2();. If it doesn't exist, it isn't added to the tags vector. This is the check - if(d->ID3v2Location >= 0).
However, at the end of the function, just before returning, we have -
// Make sure that we have our default tag types available.
ID3v2Tag(true);
ID3v1Tag(true);
Now, Id3v2Tag(create) with a true parameter, actually calls return d->tag.access(ID3v2Index, create);. The access() function is -
template <class T> T *access(int index, bool create)
{
if(!create || tag(index))
return static_cast<T *>(tag(index));
set(index, new T);
return static_cast<T *>(tag(index));
}
So when create is true, we are creating a brand new, empty tag and placing it in the vector (using the set() function).
This means that no matter whether the file contains the tags or not, they are added to the vector. This isn't the documented behavior. Looks like a bug.
I don't know why these two lines are needed there - looking at the history of this file might hint as to why they were added, but I didn't do that.
Anyway, I want to stress that I never actually executed this code. This is based on purely statically reading only very small parts, without being aware of large scale issues.
I think that opening a bug report can't hurt.
Using a null pointer doesn't necessarily result in any error you can see; it's undefined behavior. It might appear to work, or it might do something really really weird.
In this case the compiler is probably generating a call to TagLib::ID3v2::Tag::album with the this pointer set to null, but even this is not guaranteed. What happens inside the function is anyone's guess.
If the function can return NULL, you should be explicitly checking for it and doing something different.
Taglib create an "Empty" ID3v2Tag and ID3v1Tag in the object if the file do not have one.
I am having simmilar problem and hopefully I've found workaround for ID3v1/ID3v2 presence checking.
It's method virtual bool TagLib::Tag::isEmpty() const