Forward-declare struct which only has definition in a library cpp - c++

I'm using the bullet 3 physics library, which has the following struct definition inside one of the cpps:
struct btSingleContactCallback : public btBroadphaseAabbCallback
{
btCollisionObject* m_collisionObject;
btCollisionWorld* m_world;
btCollisionWorld::ContactResultCallback& m_resultCallback;
btSingleContactCallback(btCollisionObject* collisionObject, btCollisionWorld* world,btCollisionWorld::ContactResultCallback& resultCallback)
:m_collisionObject(collisionObject),
m_world(world),
m_resultCallback(resultCallback)
{
}
virtual bool process(const btBroadphaseProxy* proxy)
{
btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
if (collisionObject == m_collisionObject)
return true;
//only perform raycast if filterMask matches
if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
{
btCollisionObjectWrapper ob0(0,m_collisionObject->getCollisionShape(),m_collisionObject,m_collisionObject->getWorldTransform(),-1,-1);
btCollisionObjectWrapper ob1(0,collisionObject->getCollisionShape(),collisionObject,collisionObject->getWorldTransform(),-1,-1);
btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(&ob0,&ob1);
if (algorithm)
{
btBridgedManifoldResult contactPointResult(&ob0,&ob1, m_resultCallback);
//discrete collision detection query
algorithm->processCollision(&ob0,&ob1, m_world->getDispatchInfo(),&contactPointResult);
algorithm->~btCollisionAlgorithm();
m_world->getDispatcher()->freeCollisionAlgorithm(algorithm);
}
}
return true;
}
};
The problem is, the struct is never declared in any of the headers, I need to be able to create an object of this type however. The bullet libraries are statically linked, so I figured I should just be able to declare it myself in my main program as such:
struct btSingleContactCallback
: public btBroadphaseAabbCallback
{
btCollisionObject *m_collisionObject;
btCollisionWorld *m_world;
btCollisionWorld::ContactResultCallback &m_resultCallback;
btSingleContactCallback(btCollisionObject *collisionObject,btCollisionWorld *world,btCollisionWorld::ContactResultCallback &resultCallback);
virtual bool process(const btBroadphaseProxy *proxy);
};
This actually works fine, as long as I'm compiling in debug mode. However, when trying to compile in release mode, I'm getting an unresolved symbol error:
physenvironment.obj : error LNK2001: unresolved external symbol "public: __cdecl btSingleContactCallback::btSingleContactCallback(class btCollisionObject *,class btCollisionWorld *,struct btCollisionWorld::ContactResultCallback &)" (??0btSingleContactCallback##QEAA#PEAVbtCollisionObject##PEAVbtCollisionWorld##AEAUContactResultCallback#2##Z)
Could this have anything to do with c++'s name mangling? Is there a way to avoid it, without having to start making modifications in the library itself?

From a five minute look at the library code, you actually should use ContactResultCallback which is public, letting the implementation of btCollisionWorld::contactTest create and use the private btSingleContactCallback for you.

You did not implement the constructor.

Related

Unresolved external symbol when using static

I am new to c++. I started now playing with classes and I am having a noob problem with statics.
class Test
{
public:
Test(){};
~Test(){};
static void test();
static Helper* helper;
};
void Test::test()
{
Object obj = Test::helper->getObject();
//...
}
When I try to compile it gives the error:
main.obj : error LNK2001: unresolved external symbol "public: static class Helper* Test::helper" (?helper#Test##2PAVHelper##A)
What is wrong with my code?
The first answer is correct. The reason behind this is that you need to allocate memory for static objects outside the class definition. If you define the the class in a header file, and include it in several cpp files, the compiler doesn't know where and how you want to create the object that 'helper' points to.
you need to define Test::helper. Write something like this outside the class:
Helper* Test::helper = new Helper;

Unresolved external symbol on non-inline function body

These type of errors are well discussed on SO and many other places, yet, I couldnt find a solution to my particular case.
Basically, I have made a static library project in my solution to seperate some functionality, and reference it in my current project. When I try to call a function from the library, i got this notorious linker error. I think there are no problems in setting up the project (references, dependencies etc.) .
First, I will give some minimal example of what I am working on ( there are some third party classes )
//FileReader.h
class IBKFileReader{
public:
virtual ~IBKFileReader() {} ;
virtual void readFile(std::string fileName, pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud ) = 0 ;
};
class XYZFileReader : public IBKFileReader
{
public:
virtual void readFile(std::string fileName, pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud )
{
}
And in my code, I call readFile function on a IBKFileReader object polymorphically.
And, this part is ok, without any errors, it compiles, links and runs.
However, when I move the body of the readFile function to a .cpp file and implement it there
(with the same signature hopefully, i copy pasted) , I got the unresolved external symbol error. This is the header of the function in .cpp file.
void XYZFileReader::readFile(std::string fileName, pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud )
It seems that implementing the function body inline in the header file, and implementing in some seperate file makes a difference.
What do you think of this issue? Has anybody experienced something similar to this? I hope I am not missing out something obvious.
EDIT:
This is the error log i get:
1>main.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl XYZFileReader::readFile(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class boost::shared_ptr<class pcl::PointCloud<struct pcl::PointXYZ> >)" (?readFile#XYZFileReader##UEAAXV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##V?$shared_ptr#V?$PointCloud#UPointXYZ#pcl###pcl###boost###Z)
EDIT:
I may have caused some misunderstanding.
FileReader.h and FileReader.cpp is in static library project. I didnt do more than just implementing the function in the cpp file, definitions and such are still there.
In the same solution, in another project I reference to this project.
I am not getting the linker error when compiling the static lib, but when I am using it.
Sorry for my bad English.
A member function that is defined inside its class member list is called an inline member function. Try moving the member definition out of the class definition.
class XYZFileReader : public IBKFileReader
{
public:
virtual void readFile(std::string fileName,
pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud);
};
void XYZFileReader::readFile(std::string fileName,
pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud) {}

Linker can't find function definitions, LNK2001 unresolved external symbol

Here is my simple setup: (i've hidden lots of unneeded information)
//AutoFocusTest.h
#include "camAVTEx.h"
class CAutoFocusTestApp : public CWinApp
{
protected:
camera_t* mCamera;
public:
virtual BOOL InitInstance();
};
//camAVTEx.h
class camera_avtcam_ex_t : public camera_t
{
public:
camera_avtcam_ex_t();
virtual ~camera_avtcam_ex_t();
//member variables
//member function declarations
}
//camAVTEx.cpp
#include "camAVTEx.h"
camera_avtcam_ex_t::camera_avtcam_ex_t()
{
//stuff
}
camera_avtcam_ex_t::~camera_avtcam_ex_t()
{
//stuff
}
//the rest are defined here in my program
//AutoFocusTest.cpp
#include AutoFocusTest.h
BOOL CAutoFocusTestApp::InitInstance()
{
mCamera = new camera_avtcam_ex_t();
}
This setup produces the error:
3>AutoFocusTest.obj : error LNK2001: unresolved external symbol
"public: __cdecl camera_avtcam_ex_t::camera_avtcam_ex_t(void)"
(??0camera_avtcam_ex_t##QEAA#XZ)
From everything I've read on this relatively common problem, I have not linked something causing my camera_avtcam_ex_t function definitions to not be found. However, I can't figure out what I could have missed. I have added all of the include directories and library directories, as well as added the library files to the additional dependencies section.
Can anyone spot anything that I might be missing?
Assuming you have defined the constructor for your camera_avtcam_ex_t, it's declared as private, you can't instantiate it.

Linker Errors and Rebuilds. Are they preventable?

I was getting the following error from Visual Studio:
error LNK2019: unresolved external symbol "public: __thiscall BSTree::BSTreeNode::BSTreeNode(class TestData const &,class BSTree::BSTreeNode *,class BSTree::BSTreeNode *)" (??0BSTreeNode#?$BSTree#VTestData##H##QAE#ABVTestData##PAV01#1#Z) referenced in function "protected: void __thiscall BSTree::insertHelper(class TestData const &,class BSTree::BSTreeNode * &)" (?insertHelper#?$BSTree#VTestData##H##IAEXABVTestData##AAPAVBSTreeNode#1##Z)
Here are the functions that the compiler brings into question:
template < typename DataType, class KeyType >
BSTree<DataType,KeyType>::BSTreeNode::BSTreeNode ( const DataType &nodeDataItem,
BSTreeNode *leftPtr, BSTreeNode *rightPtr ) {
left = leftPtr;
right = rightPtr;
dataItem = nodeDataItem;
}
template < typename DataType, class KeyType >
void BSTree<DataType,KeyType>::insertHelper (const DataType& d, BSTreeNode*& b) {
if (b == 0) {
b = new BSTreeNode(d, 0, 0);
}
else if (d.getKey() < b->dataItem.getKey()) {
insertHelper(d, b->left);
}
else if (d.getKey() > b->dataItem.getKey()) {
insertHelper(d, b->right);
}
else {
b->dataItem = d;
}
}
So I look them over and I believe my code looks correct. So I perform a rebuild and then there are no errors and the program fires up just fine. I asked my lab instructor about why this occurs, but he said that he did not have a suitable answer. This is something that I've seen more and more while my projects are becoming more complex.
I've done some research:
Difference between build, rebuild, and clean solution
Do I always need to Clean/Rebuild?
Is this something that just inevitably happens while working with the Visual Studio IDE? Is there anything that I can do to prevent this? Are there any consequences from having this issue come up (ie. is there a flaw in my code)?
UPDATED: It seems that this might be the cause for much of the linker errors that I've been witnessing the semester.
Here is the advice from a book:
"Compiling programs that use templated classes requires a change in what files are included using the #include preprocessor directive, and in how the program is compiled. Because of how C++ compilers process templated code, the program that creates objects of the classes (e.g., main.cpp) must include the class implementation file, not the class declaration file. That is, it must do #include "Classname.cpp" instead of the usual #include "Classname.h" The rule is in effect the rest of this book. Because the main implementation file does a #include of the class implementation code, the class implementation code is not compiled separately."

C++ LNK2019 error with constructors and destructors in derived classes

I have two classes, one inherited from the other. When I compile, I get the following errors:
Entity.obj : error LNK2019: unresolved external symbol "public: __thiscall Utility::Parsables::Base::Base(void)" (??0Base#Parsables#Utility##QAE#XZ) referenced in function "public: __thiscall Utility::Parsables::Entity::Entity(void)" (??0Entity#Parsables#Utility##QAE#XZ)
Entity.obj : error LNK2019: unresolved external symbol "public: virtual __thiscall Utility::Parsables::Base::~Base(void)" (??1Base#Parsables#Utility##UAE#XZ) referenced in function "public: virtual __thiscall Utility::Parsables::Entity::~Entity(void)" (??1Entity#Parsables#Utility##UAE#XZ)
D:\Programming\Projects\Caffeine\Debug\Caffeine.exe : fatal error LNK1120: 2 unresolved externals
I really can't figure out what's going on.. can anyone see what I'm doing wrong? I'm using Visual C++ Express 2008. Here are the files..
"include/Utility/Parsables/Base.hpp"
#ifndef CAFFEINE_UTILITY_PARSABLES_BASE_HPP
#define CAFFEINE_UTILITY_PARSABLES_BASE_HPP
namespace Utility
{
namespace Parsables
{
class Base
{
public:
Base( void );
virtual ~Base( void );
};
}
}
#endif //CAFFEINE_UTILITY_PARSABLES_BASE_HPP
"src/Utility/Parsables/Base.cpp"
#include "Utility/Parsables/Base.hpp"
namespace Utility
{
namespace Parsables
{
Base::Base( void )
{
}
Base::~Base( void )
{
}
}
}
"include/Utility/Parsables/Entity.hpp"
#ifndef CAFFEINE_UTILITY_PARSABLES_ENTITY_HPP
#define CAFFEINE_UTILITY_PARSABLES_ENTITY_HPP
#include "Utility/Parsables/Base.hpp"
namespace Utility
{
namespace Parsables
{
class Entity : public Base
{
public:
Entity( void );
virtual ~Entity( void );
};
}
}
#endif //CAFFEINE_UTILITY_PARSABLES_ENTITY_HPP
"src/Utility/Parsables/Entity.cpp"
#include "Utility/Parsables/Entity.hpp"
namespace Utility
{
namespace Parsables
{
Entity::Entity( void )
{
}
Entity::~Entity( void )
{
}
}
}
The relevant bit is this:
unresolved external symbol "public: __thiscall Utility::Parsables::Base::Base(void)"
You need to provide a definition for Base::Base and Base::~Base. A declaration is not good enough. Even if you have nothing to do in either function, you need to leave an empty function body, because C++ actually requires the function to exist. C++ puts things like virtual table maintenance inside your constructors and destructors, so they must be defined even if you don't need to do anything there -- C++ has to do things in there.
Are you sure Base.cpp is being included in the build?
Just encountered this exact same error today in Visual Studio 2015. Unfortunately the accepted answer didn't worked (as well as answers from many same questions). The thing that worked for me was right click on the base class cpp file, exclude and then include it again. I think somehow VS got confused while moving file around and renames and it just silently refused to compile it even though it was marked as "Included In project" = true in property editor as well as listed in vcproj file in group. This is horrible error and ended up spending good hour on it.
Either your base.cpp is not being compiled/linked or you have a misspelling in it