Sign in to follow this  
incertia

Odd unresolved external symbol to nonexistent constructor

Recommended Posts

So once upon a time I wrote an interface
 
struct IC_API Infinity::IEventManager {
	virtual INFINITY_VOID	INFINITY_CALL	AttachEventListener(INFINITY_GUID EventID, EventCallback_t f) = 0;
	virtual INFINITY_VOID	INFINITY_CALL	DetachEventListener(INFINITY_GUID EventID, EventCallback_t f) = 0;			//maybe with std::find?
	virtual INFINITY_VOID	INFINITY_CALL	TriggerEvent(IEvent *e) = 0;
};
and something that implemented that interface in another project
class CEventManager : public Infinity::IEventManager {
public:
	CEventManager() {}
	~CEventManager() {}

	//GUID comparison functor
	typedef struct {
		bool operator()(const INFINITY_GUID &left, const INFINITY_GUID &right){
			if(left.Data1 < right.Data1) return true;
			if(left.Data2 < right.Data2) return true;
			if(left.Data3 < right.Data3) return true;
			for(register size_t i = 0; i < 8; i++)
				if(left.Data4[i] < right.Data4[i]) return true;
			return false;
		}
	} GUIDComparer;

	virtual INFINITY_VOID		INFINITY_CALL	AttachEventListener(INFINITY_GUID EventType, Infinity::EventCallback_t f){
		//Just insert it
		event_map[EventType].insert(f);
	}

	virtual INFINITY_VOID		INFINITY_CALL	DetachEventListener(INFINITY_GUID EventType, Infinity::EventCallback_t f){
		//See if the event type has any listeners
		auto it = event_map.find(EventType);
		if(it != event_map.end()){
			//If so, see if it has our listener function
			auto func_it = it->second.find(f);
			if(func_it != it->second.end()){
				//Then remove it
				it->second.erase(func_it);
			}
		}
	}

	virtual INFINITY_VOID		INFINITY_CALL	TriggerEvent(Infinity::IEvent *e){
		//Launch listeners
		INFINITY_GUID magic = e->GetEventType();
		std::for_each(event_map[magic].begin(), event_map[magic].end(), [&] (Infinity::EventCallback_t f) -> INFINITY_VOID { f(e); });

		delete e;		//Because it's called with something like TriggerEvent(new IEvent(...));
	}
private:
	//Global event listener storage for each event
	//Maps (GUID EventType) -> set of listener functions
	std::map<INFINITY_GUID, std::set<Infinity::EventCallback_t>, GUIDComparer> event_map;
};
except I'm getting an unresolved external symbol to an undefined constructor:
 
error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall Infinity::IEventManager::IEventManager(void)" (__imp_??0IEventManager@Infinity@@QAE@XZ) referenced in function "public: __thiscall CEventManager::CEventManager(void)" (??0CEventManager@@QAE@XZ)
 

Any ideas on what could be causing this problem? Edited by incertia

Share this post


Link to post
Share on other sites

I'm going to guess you need a virtual destructor defined in your Infinity::IEventManager interface:

struct IC_API Infinity::IEventManager {
	virtual INFINITY_VOID	INFINITY_CALL	AttachEventListener(INFINITY_GUID EventID, EventCallback_t f) = 0;
	virtual INFINITY_VOID	INFINITY_CALL	DetachEventListener(INFINITY_GUID EventID, EventCallback_t f) = 0;			//maybe with std::find?
	virtual INFINITY_VOID	INFINITY_CALL	TriggerEvent(IEvent *e) = 0;
        virtual ~IEventManager() {} 
};

Share this post


Link to post
Share on other sites

Are you properly including the definition of Infinity::IEventManager prior to the class deriving from it?

Yes I am.
 

I'm going to guess you need a virtual destructor defined in your Infinity::IEventManager interface:

struct IC_API Infinity::IEventManager {
	virtual INFINITY_VOID	INFINITY_CALL	AttachEventListener(INFINITY_GUID EventID, EventCallback_t f) = 0;
	virtual INFINITY_VOID	INFINITY_CALL	DetachEventListener(INFINITY_GUID EventID, EventCallback_t f) = 0;			//maybe with std::find?
	virtual INFINITY_VOID	INFINITY_CALL	TriggerEvent(IEvent *e) = 0;
        virtual ~IEventManager() {} 
};

Adding and defining a virtual destructor like that gives me yet another unresolved external error.

Share this post


Link to post
Share on other sites

Either your constructor is not being exported from its DLL, or you are not linking properly to your other project. I think, if you explicitly declare the constructor and implement it in a cpp file, you'll be able to make sure it gets exported.

Share this post


Link to post
Share on other sites

Your post had me curious about DLL exports.  Apparently if you wanted to just define an interface in a DLL you can create an empty .cpp module that simply includes your interface definition.  I didn't get a chance to try it though.

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