Odd unresolved external symbol to nonexistent constructor

Started by
5 comments, last by Cosmic314 10 years, 8 months ago
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?
what
Advertisement
Are you properly including the definition of Infinity::IEventManager prior to the class deriving from it?

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() {} 
};

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.
what

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.

So I realized that exporting interfaces from a DLL made no sense... not exporting it made everything work.
what

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.

This topic is closed to new replies.

Advertisement