This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 8 years ago.
I have a compiling problem in my project. I have read tons of post with this error on the title but I couldn't fix it.
I am receiving this error:
Error 4 error LNK2019: unresolved external symbol "public: class vtkUnstructuredGrid * __thiscall volumerendering::volume(class itk::SmartPointer<class itk::Image<unsigned short,3> >,class itk::SmartPointer<class itk::Image<int,3> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?volume#volumerendering##QAEPAVvtkUnstructuredGrid##V?$SmartPointer#V?$Image#G$02#itk###itk##V?$SmartPointer#V?$Image#H$02#itk###4#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z) referenced in function __catch$_main$0 a.obj
Error 5 fatal error LNK1120: 1 unresolved externals C:\Users\SERAP\Desktop\programlar\vnewb\Debug\DICOM.exe
The code is the following:
a.cpp
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif
#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif
#include "volumerendering.h"
#include "itkImage.h"
#include "itkImageSeriesReader.h"
#include "itkImageFileWriter.h"
#include "itkNumericSeriesFileNames.h"
#include "itkPNGImageIO.h"
#include "itkTIFFImageIO.h"
#include <vtkXMLUnstructuredGridWriter.h>
// Software Guide : EndCodeSnippet
#include <list>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include<itkRGBPixel.h>
#include "itkThresholdImageFilter.h"
#include "itkGDCMSeriesFileNames.h"
#include "itkGDCMImageIO.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkImageActor.h"
#include "vtkInteractorStyleImage.h"
#include "vtkRenderer.h"
#include"vtkImageViewer2.h"
#include <vtkSliderWidget.h>
#include <vtkSliderRepresentation2D.h>
#include <vtkSTLWriter.h>
// Software Guide : EndCodeSnippet
int main( int argc, char ** argv )
{
// Verify the number of parameters in the command line
if( argc < 6 )
{
std::cerr << "Usage: " << std::endl;
std::cerr << argv[0] << " firstSliceValue lastSliceValue outputImageFile OrjinalDicomDirectory Alanhesabı(txt)DosyasıAdı" << std::endl;
return EXIT_FAILURE;
}
typedef unsigned short PixelType;
const unsigned int Dimension = 3;
typedef itk::Image< PixelType, Dimension > ImageType;
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// The image type is used as a template parameter to instantiate
// the reader and writer.
//
// \index{itk::ImageSeriesReader!Instantiation}
// \index{itk::ImageFileWriter!Instantiation}
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
typedef itk::ImageSeriesReader< ImageType > ReaderType;
ReaderType::Pointer reader = ReaderType::New();
const unsigned int first = atoi( argv[1] );
const unsigned int last = atoi( argv[2] );
typedef itk::NumericSeriesFileNames NameGeneratorType;
NameGeneratorType::Pointer nameGenerator = NameGeneratorType::New();
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// The filenames generator requires us to provide a pattern of text for the
// filenames, and numbers for the initial value, last value and increment to be
// used for generating the names of the files.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
nameGenerator->SetSeriesFormat( "trabekuler%03d.tiff" );
nameGenerator->SetStartIndex( first );
nameGenerator->SetEndIndex( last );
nameGenerator->SetIncrementIndex( 1 );
reader->SetImageIO( itk::TIFFImageIO::New() );
//reader->SetImageIO( itk::PNGImageIO::New() );
reader->SetFileNames( nameGenerator->GetFileNames() );
reader->Update();
typedef int PixelType1;
const unsigned int Dimension1 = 3;
typedef itk::Image< PixelType1, Dimension1 > ImageType1;
typedef itk::ImageSeriesReader< ImageType1 > ReaderType1;
typedef itk::GDCMImageIO ImageIOType;
typedef itk::GDCMSeriesFileNames NamesGeneratorType;
ImageIOType::Pointer gdcmIO = ImageIOType::New();
NamesGeneratorType::Pointer namesGenerator1 = NamesGeneratorType::New();
namesGenerator1->SetInputDirectory( argv[4] );
const ReaderType1::FileNamesContainer & filenames1 =
namesGenerator1->GetInputFileNames();
unsigned int numberOfFilenames1 = filenames1.size();
std::cout << numberOfFilenames1 << std::endl;
for(unsigned int fni1 = 0; fni1<numberOfFilenames1; fni1++)
{
std::cout << "filename # " << fni1 << " = ";
std::cout << filenames1[fni1] << std::endl;
}
ReaderType1::Pointer reader1 = ReaderType1::New();
reader1->SetImageIO( gdcmIO );
reader1->SetFileNames( filenames1 );
try
{
// Software Guide : BeginCodeSnippet
reader1->Update();
// Software Guide : EndCodeSnippet
}
catch (itk::ExceptionObject &excp)
{
std::cerr << "Exception thrown while writing the image" << std::endl;
std::cerr << excp << std::endl;
return EXIT_FAILURE;
}
ImageType1::Pointer image=reader1->GetOutput();
typedef itk::MetaDataDictionary DictionaryType;
const DictionaryType & dictionary = gdcmIO->GetMetaDataDictionary();
typedef itk::MetaDataObject< std::string > MetaDataStringType;
std::string entryId = "0010|0010";
DictionaryType::ConstIterator end = dictionary.End();
DictionaryType::ConstIterator tagItr = dictionary.Find( entryId );
if( tagItr == end )
{
std::cerr << "Tag " << entryId;
std::cerr << " not found in the DICOM header" << std::endl;
return EXIT_FAILURE;
}
MetaDataStringType::ConstPointer entryvalue =
dynamic_cast<const MetaDataStringType *>( tagItr->second.GetPointer() );
std::string filename2 = argv[5];
if( entryvalue )
{
std::string tagvalue = entryvalue->GetMetaDataObjectValue();
std::cout << "Patient's Name (" << entryId << ") ";
std::cout << " is: " << tagvalue << std::endl;
std::ofstream myfile;
myfile.open(filename2.c_str(),std::ios::app);
myfile<< "Patient's Name: "<<tagvalue<<std::endl;
myfile .close();
}
else
{
std::cerr << "Entry was not of string type" << std::endl;
return EXIT_FAILURE;
}
//hacim ve alan hesabi
ImageType::SizeType si;
si=reader->GetOutput()->GetLargestPossibleRegion().GetSize();
ImageType::IndexType pixelIndex;
ImageType1::SpacingType sp;
sp=image->GetSpacing();
std::ofstream myfile;
myfile.open(filename2.c_str(),std::ios::app);
myfile<< "\n"<<std::endl;
myfile<< "Areas: "<<std::endl;
myfile<< "\n"<<std::endl;
double alann=sp[1]*sp[0];
for(int k=si[2]-1;k>-1;k--)
{
int sayii=0;
for(int i=0;i<si[0];i++)
{
for(int j=0;j<si[1];j++)
{
pixelIndex[0] = i; // x position
pixelIndex[1] =j ; // y position
pixelIndex[2]= k;
if(reader->GetOutput()->GetPixel(pixelIndex)==255)
{
sayii=sayii+1;
}
}
}
myfile<< "filename: "<<filenames1[k]<<" "<<"Area : "<<alann*sayii<<" mm_2"<<std::endl;
}
myfile .close();
// end hacim
volumerendering * vol = new volumerendering;
std::string filename = argv[3];
vtkSmartPointer<vtkXMLUnstructuredGridWriter> writer =
vtkSmartPointer<vtkXMLUnstructuredGridWriter>::New();
writer->SetFileName(filename.c_str());
writer->SetInput( vol->volume(reader->GetOutput(),image,filename2));
writer->Write();
return EXIT_SUCCESS;
}
volumerendering.cpp
#ifndef _volumerendering_cpp
#define _volumerendering_cpp
#include"volumerendering.h"
#include <vtkSmartPointer.h>
#include <vtkDataSetMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkPoints.h>
#include <vtkVoxel.h>
#include <vtkUnstructuredGrid.h>
#include <vtkParticleReader.h>
#include <vtkProperty.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkDataSetSurfaceFilter.h>
#include <vtkPointSource.h>
#include <vtkPointData.h>
#include <vtkSTLWriter.h>
#include <vtkVertexGlyphFilter.h>
#include<vtkPolyDataWriter.h>
vtkUnstructuredGrid* volumerendering::volume(itk::Image<unsigned short,3>::Pointer image,itk::Image<int,3>::Pointer image1,std::string outt )
{
vtkUnstructuredGrid *ug = vtkUnstructuredGrid::New();
vtkSmartPointer<vtkPoints> points =vtkSmartPointer<vtkPoints>::New();
typedef itk::Image< unsigned short, 3 > ImageType;
typedef itk::Image< int, 3 > ImageType1;
ImageType::SizeType si;
si=image->GetLargestPossibleRegion().GetSize();
ImageType::IndexType pixelIndex;
ImageType1::SpacingType sp;
sp=image1->GetSpacing();
// hacim vee alan hesapları
double hacim=sp[1]*sp[0]*sp[2];
//hacim ve alan hesabi son
int fr=0;
int hacimsayii=0;
for(int i=0;i<si[0];i++)
{
for(int j=0;j<si[1];j++)
{
for(int k=0;k<si[2];k++)
{
pixelIndex[0] = i; // x position
pixelIndex[1] =j ; // y position
pixelIndex[2]= k;
if(image->GetPixel(pixelIndex)==255)
{hacimsayii=hacimsayii+1;
float a1[]={i*sp[0],j*sp[1],k*sp[2]};
float a2[]={(i+1)*sp[0],j*sp[1],k*sp[2]};
float a3[]={i*sp[0],(j+1)*sp[1],k*sp[2]};
float a4[]={(i+1)*sp[0],(j+1)*sp[1],k*sp[2]};
float a5[]={i*sp[0],j*sp[1],(k+1)*sp[2]};
float a6[]={(i+1)*sp[0],j*sp[1],(k+1)*sp[2]};
float a7[]={i*sp[0],(j+1)*sp[1],(k+1)*sp[2]};
float a8[]={(i+1)*sp[0],(j+1)*sp[1],(k+1)*sp[2]};
points->InsertPoint(fr,a1);
points->InsertPoint(fr+1,a2);
points->InsertPoint(fr+2,a3);
points->InsertPoint(fr+3,a4);
points->InsertPoint(fr+4,a5);
points->InsertPoint(fr+5,a6);
points->InsertPoint(fr+6,a7);
points->InsertPoint(fr+7,a8);
fr=fr+8;
}
}
}
}
std::ofstream myfile;
myfile.open(outt.c_str(),std::ios::app);
myfile<< "\n"<<std::endl;
myfile<< "Volume "<<std::endl;
myfile<< "\n"<<std::endl;
myfile<< "Total Volume= "<<hacim*hacimsayii<<" mm_3"<<std::endl;
myfile .close();
static int ptr[8];
int tt=0;
int cti=points->GetNumberOfPoints();
for (int i=0;i<cti/8 ;i++)
{
for (int iy=0;iy<1;iy++)
{
ptr[0]=iy+tt; ptr[1]=iy+tt+1; ptr[2]=iy+tt+2; ptr[3]=iy+tt+3;
ptr[4]=iy+tt+4; ptr[5]=iy+tt+5; ptr[6]=iy+tt+6; ptr[7]=iy+tt+7;
ug->InsertNextCell(VTK_VOXEL,8,ptr);
tt=tt+8;
}
}
ug->SetPoints(points);
/* vtkSmartPointer<vtkDataSetMapper> mapper =
vtkSmartPointer<vtkDataSetMapper>::New();
mapper->SetInput(ug);
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderWindow->AddRenderer(renderer);
renderer->AddActor(actor);
renderer->ResetCamera();
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
renderWindow->Render();
renderWindowInteractor->Start();*/
return ug;
}
#endif
volumerendering.h
#ifndef __volumerendering_h
#define __volumerendering_h
#include"vtkUnstructuredGrid.h"
#include"itkImage.h"
#include "itkImageSeriesReader.h"
class volumerendering
{
public:
vtkUnstructuredGrid* volume(itk::Image<unsigned short,3>::Pointer image,itk::Image<int,3>::Pointer image1,std::string outt );
};
#endif
thanks
volumerendering.cpp has to be compiled with the project.
But I do not see anything that prevent volumerendering::volume from being defined, so it may be a project configuration problem ?
Make sure that volumerendering.cpp is compiled at the same time than a.cpp.
Related
I am having a problem in trying to serialize an array of unsigned char into file with GZIP compression using protobuf while playing with the library.
I think the problem might have to do with some of my syntax or misuse of API.
I have also tried std::fstream.
FYI, Windows 8.1 & VS2013 is the building environment.
scene.proto
syntax = "proto3";
package Recipe;
message Scene
{
repeated int32 imageData = 1 [packed=true];
}
source.cpp
#include <iostream>
#include <fstream>
#include <ostream>
#include <istream>
#include <string>
#include <cstdint>
#include "Scene.pb.h"
#include <google\protobuf\io\zero_copy_stream_impl.h>
#include <google\protobuf\io\gzip_stream.h>
int const _MIN = 0;
int const _MAX = 255;
unsigned int const _SIZE = 65200000;
unsigned int const _COMPRESSION_LEVEL = 10;
void randWithinUnsignedCharSize(uint8_t * buffer, unsigned int size)
{
for (size_t i = 0; i < size; ++i)
{
buffer[i] = _MIN + (rand() % static_cast<int>(_MAX - _MIN + 1));
}
}
using namespace google::protobuf::io;
int main()
{
GOOGLE_PROTOBUF_VERIFY_VERSION;
Recipe::Scene * scene = new Recipe::Scene();
uint8_t * imageData = new uint8_t[_SIZE];
randWithinUnsignedCharSize(imageData, _SIZE);
for (size_t i = 0; i < _SIZE; i++)
{
scene->add_imagedata(imageData[i]);
}
std::cout << "scene->imagedata_size() " << scene->imagedata_size() << std::endl;
{
std::ofstream output("scene.art", std::ofstream::out | std::ofstream::trunc | std::ofstream::binary);
OstreamOutputStream outputFileStream(&output);
GzipOutputStream::Options options;
options.format = GzipOutputStream::GZIP;
options.compression_level = _COMPRESSION_LEVEL;
GzipOutputStream gzipOutputStream(&outputFileStream, options);
if (!scene->SerializeToZeroCopyStream(&gzipOutputStream)) {
std::cerr << "Failed to write scene." << std::endl;
return -1;
}
}
Recipe::Scene * scene1 = new Recipe::Scene();
{
std::ifstream input("scene.art", std::ifstream::in | std::ifstream::binary);
IstreamInputStream inputFileStream(&input);
GzipInputStream gzipInputStream(&inputFileStream);
if (!scene1->ParseFromZeroCopyStream(&gzipInputStream)) {
std::cerr << "Failed to parse scene." << std::endl;
return -1;
}
}
std::cout << "scene1->imagedata_size() " << scene1->imagedata_size() <<std::endl;
google::protobuf::ShutdownProtobufLibrary();
return 0;
}
You seem to have a typo in your code. Compression level is according to documentation in range 0-9. You set incorrectly compression level to 10.
Your example is working for me when corrected to:
unsigned int const _COMPRESSION_LEVEL = 9;
I'm trying to run multiple geometric calculations with CGAL simultaneously in multiple threads. All threads are 100% "isolated" from each other. Nevertheless the app crashes with an access violation:
http://s8.postimg.org/52u9qphdx/error.png
I've build a small example app to reproduce the error:
main.cpp
#include <fstream>
#include "windows.h"
#include "cTestClass.h"
int main ( int argc, char *argv[] ){
cTestClass *eval0 = new cTestClass("d://.partion_2.stl", 0);
cTestClass *eval1 = new cTestClass("d://.partion_2.stl", 1);
eval0->start_eval();
eval1->start_eval();
while (!eval0->eval_finished())
{
Sleep(200);
}
while (!eval1->eval_finished())
{
Sleep(200);
}
return EXIT_SUCCESS;
}
cTestClass.h
#ifndef CTEST_CLASS_H
#define CTEST_CLASS_H
#include <atomic>
#include <thread>
class cTestClass
{
private:
std::atomic<bool> flag_eval_finished;
std::thread eval_thread;
std::string stl_file_name;
unsigned int thread_index;
cTestClass(){ }
void evaluate_partition();
public:
cTestClass(std::string argStlFile, unsigned int argThread_index);
void start_eval();
bool eval_finished();
};
#endif
cTestClass.cpp
#include "cTestClass.h"
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Nef_polyhedron_3.h>
#include <CGAL/polygon_soup_to_polyhedron_3.h>
#include <CGAL/IO/Polyhedron_builder_from_STL.h>
#include <iostream>
#include <fstream>
//typedef CGAL::Cartesian<double> Kernel;
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron_3;
typedef CGAL::Nef_polyhedron_3<Kernel> Nef_polyhedron_3;
typedef CGAL::Point_3<Kernel> Point_3;
//typedef Polyhedron::Point_iterator Point_iterator;
typedef Polyhedron_3::Vertex_iterator Vertex_iterator;
typedef Polyhedron_3::Facet_iterator Facet_iterator;
typedef Polyhedron_3::Halfedge_around_facet_circulator Halfedge_facet_circulator;
typedef Nef_polyhedron_3::Volume_const_iterator Volume_const_iterator;
typedef Kernel::Iso_cuboid_3 Iso_cuboid;
//constructor
cTestClass::cTestClass(std::string argStlFile, unsigned int argThread_index)
{
thread_index = argThread_index;
stl_file_name = argStlFile;
flag_eval_finished = false;
}
//===========================================================================================
// public member functions
void cTestClass::start_eval()
{
std::cout << "Thread " << thread_index << ": start" << std::endl;
eval_thread = std::thread(&cTestClass::evaluate_partition, this);
}
bool cTestClass::eval_finished()
{
return flag_eval_finished;
}
//===========================================================================================
//private member functions
void cTestClass::evaluate_partition()
{
//read stl file and create cgal polyhedron
Polyhedron_3 poly_Partition;
std::ifstream stl_file(stl_file_name.c_str(), std::ifstream::in);
std::vector<CGAL::cpp11::array<double, 3> > points;
std::vector<CGAL::cpp11::array<int, 3> > triangles;
CGAL::read_STL(stl_file, points, triangles);
stl_file.close();
//create polyhedron
CGAL::polygon_soup_to_polyhedron_3(poly_Partition, points, triangles);
//convert polyhedron to nef_poly representation
std::cout << "Thread " << thread_index << ": " <<"Converting partition polyhedron to Nef representation" << std::endl;
Nef_polyhedron_3 nefpoly_Partition(poly_Partition);
flag_eval_finished = true;
}
Anyone got an idea what causes this crash?
Best regards
Monchi
I'm encountering the following linker issue when I try to build my project.
I've had a look through the other posts here and as far as I can see, the only externals I'm using are members of standard (and identified with std::), or primitives. Is there something obvious that I'm missing here?
Building using Eclipse C++ (Mars) on Win 7 professional 64bit using the internal eclipse builder.
Log:
link /debug /nologo /OUT:SAD-Snoop.exe "src\ByteScanner.obj" "src\EncType.obj" "src\SAD-Snoop.obj" "src\SearchHits.obj"
SearchHits.obj : error LNK2019: unresolved external symbol "public: long __thiscall SearchHits::GetHitAddress(unsigned int)" (GetHitAddress#SearchHits##QAEJI#Z) referenced in function "public: bool __thiscall SearchHits::Merge(class SearchHits)" (?Merge#SearchHits##QAE_NV1##Z)
SAD-Snoop.exe : fatal error LNK1120: 1 unresolved externals
14:28:44 Build Finished (took 909ms)
Header:
/*
* SearchHits.h
*
* Created on: 30 Jun 2015
* Author: Nick Boyd
*/
#ifndef SEARCHHITS_H_
#define SEARCHHITS_H_
#include <iostream>
#include <string>
#include <vector>
class SearchHits {
public:
SearchHits();
~SearchHits();
bool AddHit(std::string content, long address);
unsigned int CountHits();
std::string GetHit(unsigned int hitNumber);
long GetHitAddress(unsigned int hitNumber);
bool Merge(SearchHits hits);
private:
std::vector<std::string> hits;
std::vector<long> hitAddresses;
};
#endif /* SEARCHHITS_H_ */
class:
/*
* SearchHits.cpp
*
* Created on: 30 Jun 2015
* Author: Nick Boyd
*/
#include "SearchHits.h"
#include <string>
#include <iostream>
#include <vector>
std::vector<std::string> hitContents;
std::vector<long> hitAddresses;
SearchHits::SearchHits() {
}
SearchHits::~SearchHits() {
hitContents.clear();
hitAddresses.clear();
}
bool SearchHits::AddHit(std::string hitContent, long address) {
hitContents.push_back(hitContent);
hitAddresses.push_back(address);
return ((hitContents.back() == hitContent)
&& (hitAddresses.back() == address));
}
unsigned int SearchHits::CountHits() {
return hitContents.size();
}
std::string SearchHits::GetHit(unsigned int hitNumber) {
if (hitNumber < hitContents.size()) {
return hitContents[hitNumber];
} else {
std::cout << "Error in Function [SearchHits::GetHit()]" << std::endl
<< "Parameter [hitNumber] out of bounds: "
<< hitNumber + " Upper Limit: " << hitContents.size()
<< std::endl;
throw new std::invalid_argument(
"Error in Function [SearchHits::GetHit()] Parameter [hitNumber] out of bounds: "
+ std::to_string(hitNumber));
}
}
long GetHitAddress(unsigned int hitNumber) {
if (hitNumber < hitContents.size()) {
return hitAddresses[hitNumber];
} else {
std::cout << "Error in Function [SearchHits::GetHitAddress()]"
<< std::endl << "Parameter [hitNumber] out of bounds: "
<< hitNumber << " Upper Limit: " << hitContents.size()
<< std::endl;
throw new std::invalid_argument(
"Error in Function [SearchHits::GetHitAddress()] Parameter [hitNumber] out of bounds: "
+ std::to_string(hitNumber));
}
}
bool SearchHits::Merge(SearchHits hits) {
bool overallResult = true;
unsigned int i = 0;
while ((i < hits.CountHits()) && overallResult) {
bool tempResult = false;
unsigned char attemptNum = 1;
while ((tempResult == false) && (attemptNum++ <= 5)) {
tempResult = this->AddHit(hits.GetHit(i),hits.GetHitAddress(i));
}
overallResult = (overallResult && tempResult);
++i;
}
if (overallResult) {
hits.~SearchHits();
}
return overallResult;
}
Change
long GetHitAddress(unsigned int hitNumber)
to
long SearchHits::GetHitAddress(unsigned int hitNumber)
I am getting these errors:
Error 2 error LNK2005: "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl ToString(int)" (?ToString##YA?AV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##H#Z) already defined in Sender.obj C:\CSE687\Project3_TT_1\Repository\Repository.obj
Error 3 error LNK2005: "private: static int Sender::count" (?count#Sender##0HA) already defined in Sender.obj C:\CSE687\Project3_TT_1\Repository\Repository.obj
Error 4 error LNK1169: one or more multiply defined symbols found C:\CSE687\Project3_TT_1\Debug\Repository.exe
from these three pieces of code:
#ifndef SEND_H
#define SEND_H
/////////////////////////////////////////////////////////////////
// Sender.cpp - Demonstration of concurrent socket connectors //
// ver 2 //
// Jim Fawcett, CSE687 - Object Oriented Design, Spring 2013 //
/////////////////////////////////////////////////////////////////
/*
* This Sender expects to write lines of text only.
* So message framing is done by lines.
*
* For HTTP like protocols the Sender should send lines for each
* header attribute and bytes in the body, if there is one,
* specified by a last header line something like:
* content_length : 1024
* where 1024 is a stand-in for whatever you want your block
* size to be.
*
*/
/*
* Required files:
* - Sender.cpp, Sockets.h, Sockets.cpp,
* Threads.h, Threads.cpp, Locks.h, Locks.cpp
* BlockingQueue.h, BlockingQueue.cpp
*
* Maintanence History:
* ver 1.1 - 30 Mar 2013
* - changed Sendthread from terminating to default
* - minor changes to error handling
* ver 1.0 - 29 Mar 2013
* - first release
*/
#include "../sockets/Sockets.h"
#include "../Threads/Threads.h"
#include "../Threads/Locks.h"
#include "../BlockingQueue/BlockingQueue.h"
#include <string>
#include <iostream>
#include <sstream>
///////////////////////////////////////////////////
// SendThread thread
class SendThread : public threadBase
{
public:
SendThread(Socket s, BlockingQueue<std::string>& q) : s_(s), q_(q) {}
std::string& status() { return status_; }
private:
void run()
{
status_ = "good";
doLog("send thread running");
std::string msg;
do
{
doLog("send thread enqing msg");
msg = q_.deQ();
if(!s_.writeLine(msg))
{
sout << "\n bad status in sending thread";
status_ = "bad";
break;
}
} while(msg != "stop");
s_.disconnect();
}
std::string status_;
Socket s_;
BlockingQueue<std::string>& q_;
};
std::string ToString(int i)
{
std::ostringstream conv;
conv << i;
return conv.str();
}
class Sender
{
public:
Sender() {};
Sender(int numMsgs) : numMsgs_(numMsgs) { myCount = ++count; }
int id() { return myCount; }
void start(std::string ip, int port)
{
sout << locker << "\n Sender #" << id() << " started" << unlocker;
pSt = new SendThread(s_, q_);
pSt->start();
if(!s_.connect(ip, port))
{
sout << locker << "\n couldn't connect to " << ip << ":" << port << "\n\n" << unlocker;
delete pSt;
return;
}
else
{
std::string logMsg = "\n connected to " + ip + ":" + ToString(port);
doLog(logMsg.c_str());
}
doLog("starting Sender");
std::string msg;
for(int i=0; i<numMsgs_; ++i)
{
doLog("sending message");
msg = "sender#" + ToString(id()) + ": msg#" + ToString(i);
sout << locker << "\n " << msg.c_str() << unlocker;
q_.enQ(msg);
::Sleep(10 * id()); // sleep time increases with each addition Sender
if(pSt->status() == "bad")
break;
}
q_.enQ("stop");
msg = "sender#" + ToString(id()) + ": stop";
sout << "\n " + msg;
pSt->join();
delete pSt;
}
private:
Socket s_;
BlockingQueue<std::string> q_;
SendThread* pSt;
static int count;
int myCount;
int numMsgs_;
};
int Sender::count = 0;
///////////////////////////////////////////////////
// DemoThread is used to get two or more senders
// running concurrently from a single process, to
// make testing easier.
class DemoThread : public threadBase
{
public:
DemoThread(Sender sndr) : sndr_(sndr) {}
private:
void run()
{
sndr_.start("127.0.0.1", 8080);
}
Sender sndr_;
};
#endif
and:
#ifndef REPOS_H
#define REPOS_H
/////////////////////////////////////////////////////////////////
// Recepository.h - Demonstration of repository action using a //
// socket reciever with concurrent clients //
// //
// Thomas P. Taggart //
// tptaggarsyr.edu //
// CSE687, Object Oriented Design, Spring 2013 //
/////////////////////////////////////////////////////////////////
/*
* Required files:
* - Reciever.h, Receiver.cpp, Sockets.h, Sockets.cpp,
* Threads.h, Threads.cpp, Locks.h, Locks.cpp
* BlockingQueue.h, BlockingQueue.cpp
*/
#include "../Sockets/Sockets.h"
#include "../Threads/Threads.h"
#include "../Threads/Locks.h"
#include "../Receiver/Receiver.h"
#include "../Sender/Sender.h"
#include "../BlockingQueue/BlockingQueue.h"
#include <string>
class Repository
{
public:
Repository() {};
~Repository() {};
Sender* getSender();
Receiver* getReceiver();
private:
Sender* repoSender;
Receiver* repoReceiver;
};
#endif
and:
/////////////////////////////////////////////////////////////////
// Recepository.cpp - Demonstration of repository action using //
// a socket reciever with concurrent clients //
// //
// Thomas P. Taggart //
// tptaggarsyr.edu //
// CSE687, Object Oriented Design, Spring 2013 //
/////////////////////////////////////////////////////////////////
/*
* Required files:
* - Reciever.h, Receiver.cpp, Sockets.h, Sockets.cpp,
* Threads.h, Threads.cpp, Locks.h, Locks.cpp
* BlockingQueue.h, BlockingQueue.cpp
*/
#include "../Repository/Repository.h"
#include <string>
using namespace std;
Sender* Repository::getSender()
{
return repoSender;
}
Receiver* Repository::getReceiver()
{
return repoReceiver;
}
int main()
{
int ret = 0;
try
{
Repository repos;
repos.getReceiver()->start(8080);
}
catch(std::exception& ex)
{
std::cout << "\n\n " << ex.what();
ret = 1;
}
catch(...)
{
sout << "\n something bad happened";
ret = 1;
}
sout << "\n\n";
return ret;
}
I have not for the life of me been able to figure out how to avoid it. the 'extern' solution doesn't seem to work and #ifndef headers area already used.
Any advice is greatly appreciated.
Tom
You're breaking the ODR - either make std::string ToString(int i) inline or move it to an implementation file.
The main application needs to update the shared memory at a fast frequency.
And several consuming applications need to read from the shared memory to update the streamed data.
main and consuming applications are different processes.
How to implement this with Boost.Interprocess ?
producer:
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/thread.hpp>
#include <iostream>
struct shared_data_t {
boost::uint32_t data;
boost::interprocess::interprocess_mutex mutex;
};
/***************************************************************************/
/* producer */
int main(int argc, char** argv) {
const char* shname = "_unique_object_name_";
boost::shared_ptr<const char> remover(
shname,
boost::interprocess::shared_memory_object::remove
);
try {
boost::interprocess::shared_memory_object shared_object(
boost::interprocess::create_only,
shname,
boost::interprocess::read_write
);
shared_object.truncate(sizeof(shared_data_t));
boost::interprocess::mapped_region region(
shared_object,
boost::interprocess::read_write
);
shared_data_t* data = new(region.get_address())shared_data_t;
assert(data);
const boost::uint32_t count = 0x1000;
for ( boost::uint32_t idx = 0; idx < count; ++idx ) {
{ boost::interprocess::scoped_lock<
boost::interprocess::interprocess_mutex
> lock(data->mutex);
data->data = idx;
}
boost::this_thread::sleep(boost::posix_time::seconds(1));
}
} catch(boost::interprocess::interprocess_exception &e){
std::cout << e.what() << std::endl;
return 1;
}
return 0;
}
consumer:
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/thread.hpp>
struct shared_data_t {
boost::uint32_t data;
boost::interprocess::interprocess_mutex mutex;
};
/***************************************************************************/
/* consumer */
int main(int argc, char** argv) {
try {
boost::interprocess::shared_memory_object shared_object(
boost::interprocess::open_only,
"_unique_object_name_",
boost::interprocess::read_only
);
shared_object.truncate(sizeof(shared_data_t));
boost::interprocess::mapped_region region(
shared_object,
boost::interprocess::read_only
);
shared_data_t* data = new(region.get_address())shared_data_t;
assert(data);
while ( true ) {
{ boost::interprocess::scoped_lock<
boost::interprocess::interprocess_mutex
> lock(data->mutex);
std::cout << "ping: " << data->data << std::endl;
}
boost::this_thread::sleep(boost::posix_time::milliseconds(100));
}
} catch(boost::interprocess::interprocess_exception &e){
std::cout << e.what() << std::endl;
return 1;
}
return 0;
}
man:
http://www.boost.org/doc/libs/1_43_0/doc/html/interprocess/synchronization_mechanisms.html