Sign in to follow this  
struct

unresolved external

Recommended Posts

struct    122
I've been writing some code to parse a .WAV file written in cannonical form. The data from the .WAV file is simply dumped into a matrix created using the TNT library (http://math.nist.gov/tnt/). However, when I compile the code, I get the following error from the compiler (VC++ 2005): ------ Build started: Project: WaveReaderClass, Configuration: Debug Win32 ------ Linking... test.obj : error LNK2019: unresolved external symbol "public: class TNT::Array1D<short> * __thiscall WaveReader::getSoundData(void)" (?getSoundData@WaveReader@@QAEPAV?$Array1D@F@TNT@@XZ) referenced in function _main P:\WaveReaderClass\WaveReaderClass\Debug\WaveReaderClass.exe : fatal error LNK1120: 1 unresolved externals Build log was saved at "file://p:\snowDensity\WaveReaderClass\WaveReaderClass\WaveReaderClass\Debug\BuildLog.htm" WaveReaderClass - 2 error(s), 0 warning(s) ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== Where am I going wrong? I've searched the forums on GameDev.net. Apparently, I need to include the TNT::Array1D class so that it is visible to both the function definitions in the header files and main() in the driver class. Here are the other files that I am working with. //////////////////////////////////////////////////////////////// //Program to test the waveReader classes #include <iostream> #include <cstdlib> //Template Numerical Toolkit #include "\common\tnt\tnt_array1d.h" //Header file #include "waveReader.h" int main() { WaveReader readWave; TNT::Array1D<short int> testSoundData; if (!readWave.loadFile("test_1.wav")) { std::cout << "\nThe .WAV file could not be loaded\n"; exit(1); } //Test out the classes std::cout << "The length of the file is " << readWave.getFileLength() << "\n"; std::cout << "The format tag of the file is " << readWave.getFormatTag() << "\n"; std::cout << "The number of channels in the file is " << readWave.getChannelNum() << "\n"; std::cout << "The number of samples per second in the file is " << readWave.getSamplesPerSecond() << "\n"; std::cout << "The sample rate * block align of the file is " << readWave.getSampleRateTimesBlockAlign() << "\n"; std::cout << "The channel descriptor is " << readWave.getChannelDescriptor() << "\n"; std::cout << "The function to get the number of bits per sample is " << readWave.getBitsPerSample() << "\n"; std::cout << "The length of the data block is " << readWave.getLengthOfDataBlock() << "\n"; std::cout << "The sound data array is:\n"; //Set the pointer in this file to the memory location of the data array testSoundData = *readWave.getSoundData(); for (int i = 0; i < testSoundData.dim(); i++) std::cout << testSoundData[i] << "\n"; std::cout << "That's all folks.\n"; return 0; }//end main //////////////////////////////////////////////////////////////// /Program to be able to read the cannonical .WAV file //Assume that the data is stored as 2's complement signed integers #include <iostream> #include <fstream> //Template Numerical Toolkit #include "\common\tnt\tnt_array1d.h" //Header Files #include "WaveReader.h" //Pointer of array containing sound data TNT::Array1D<short int> soundData; //Default constructor WaveReader::WaveReader() { } //Function to read the sound wave from the file bool WaveReader::loadFile(std::string fileName) { std::ifstream inFile(fileName.c_str(), std::ios::in | std::ios::binary); if (!inFile) { //Indicate that the file could not be opened return false; } //Begin parsing the file inFile.seekg(4); inFile.read((char *)&fileLengthSubtract8, 4); fileLength = fileLengthSubtract8 + 8; inFile.seekg(20); inFile.read((char *)&formatTag, 2); inFile.read((char *)&channelNumber, 2); inFile.read((char *)&samplesPerSecond, 4); inFile.read((char *)&sampleRateTimesBlockAlign, 4); inFile.read((char *)&channelDescriptor, 2); inFile.read((char *)&bitsPerSample, 2); inFile.seekg(40); inFile.read((char *)&lengthOfDataBlock, 4); //Extract all of the sample data int counter = 0; int dataBlockSampleNum = lengthOfDataBlock / 2; while (true) { inFile.read((char *)&dataValue, 2); if (inFile.eof()) break; soundData[counter++] = dataValue; } //Close the file inFile.close(); return true; }//end loadFile //Function to get the length of the file int WaveReader::getFileLength() { return fileLength; } //Function to get the format tag of the file int WaveReader::getFormatTag() { return formatTag; } //Function to get the number of channels int WaveReader::getChannelNum() { return channelNumber; } //Function to get the samples per second int WaveReader::getSamplesPerSecond() { return samplesPerSecond; } //Function to get the sample rate * block align int WaveReader::getSampleRateTimesBlockAlign() { return sampleRateTimesBlockAlign; } //Function to get the channel descriptor int WaveReader::getChannelDescriptor() { return channelDescriptor; } //Function to get the number of bits per sample int WaveReader::getBitsPerSample() { return bitsPerSample; } //Function to get the length of the data block int WaveReader::getLengthOfDataBlock() { return lengthOfDataBlock; } //Function that returns a reference to the sound data array TNT::Array1D<short int> *getSoundData() { return &soundData; } //////////////////////////////////////////////////////////////// //Header file for the WaveReader class #ifndef WAVEREADER_H #define WAVEREADER_H class WaveReader { public: //Constructor WaveReader(); //Function to load the file bool loadFile(std::string fileName); //Accessor to get the file length int getFileLength(); //Accessor to get the format tag of the file int getFormatTag(); //Accessor to get the number of channels int getChannelNum(); //Accessor to get the number of samples per second int getSamplesPerSecond(); //Accessor to get the sample rate * block align int getSampleRateTimesBlockAlign(); //Accessor to get the channel descriptor int getChannelDescriptor(); //Accessor to hold the bits per sample int getBitsPerSample(); //Accessor to get the length of the data block int getLengthOfDataBlock(); //Function to get the matrix containing all of the data TNT::Array1D<short int> *getSoundData(); private: //RIFF Header //Variable to hold the fileLength - 8 int fileLengthSubtract8; //Variable to hold the fileLength int fileLength; //FMT Chunk //Variable to hold the format tag (1 = PCM) int formatTag; //Variable to hold the number of channels int channelNumber; //Variable to hold the samples per second int samplesPerSecond; //Variable to hold the sampleRate * block align int sampleRateTimesBlockAlign; //Variable to hold the channel descriptor int channelDescriptor; //Variable to hold the bits per sample int bitsPerSample; //Data Chunk //Variable to hold the length of the data block int lengthOfDataBlock; //Variable to hold a 16-bit data value as two's complement short int dataValue; };//end class WaveReader #endif //////////////////////////////////////////////////////////////// Thank you!

Share this post


Link to post
Share on other sites
Bob Janova    769
Are you sure (a) you've included the right file (b) you've spelt the name of the function right (c) you've included the right namespace, if necessary (d) you have the right version of the library you're using? The error is a simple 'cannot find' one, so it must be something along those lines.

Share this post


Link to post
Share on other sites
struct    122
Thanks for the reply! I have checked the includes for all of the files, and it seems that everything should work. I think that the problem is associated with a type of cyclic dependency, where the linker has included the TNT::Array1D class twice, and thus cannot reference the proper function (because there are two copies included in the object file). How do I ensure that the compiler 'knows' that the TNT::Array1D class is referred to in the header file (without getting some sort of linker error)?

Once again, thank you for your help!

Share this post


Link to post
Share on other sites
Kylotan    10008
If you had 2 copies of the function, you'd have been given a different error message. This message is because it can't even find 1 copy of the function.

The problem is that the function you have written is a global function, but the function you have tried to use is a member function, which naturally doesn't exist.

Share this post


Link to post
Share on other sites
JohnBolton    1372
Sometimes, error messages are difficult to decipher because they contain too much information. The problem is exactly what it says -- you are missing the function WaveReader::getSoundData().

However, you implemented the function getSoundData(). I assume that's a typo.

Also, when posting code you should enclose it using [ code ] and [ /code ] or [ source ] and [ /source ].

Share this post


Link to post
Share on other sites
struct    122
Thank you to all the people who replied! I really, really appreciate this! Once again, thank you. I'll enclose the code in [ code ] and [ /code ] when I make my next post. Thanks Kylotan and JohnBolton!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this