Solved

C++ Unresolved References

Posted on 2011-03-24
16
835 Views
Last Modified: 2012-05-11
I am getting unresolved references and am have a heck of a time trying to sort this out. The reference issues are localized to two class (H/.CPP) files only. These files were part of a .DLL and were moved to a MFC/DLL for troubleshooting.. It seems there is nothing I can change that will make the VS 2010 resolve these references.
The include directories are mapped to the project directory.
The lib directory is mapped to the project directory.


Thanks

1>MyFile.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: virtual __thiscall _ScheduleFileLock::~_ScheduleFileLock(void)"

#pragma once

// _ScheduleFileLock command target

AFX_STATIC_DATA TCHAR _RCScheduleLock[] = _T("C:\\ENVY\\RCScheduleLock.DAT");
class _ScheduleFileLock : public CObject
{
public:
	_ScheduleFileLock();
	virtual ~_ScheduleFileLock();

	VOID	Dispose();
	BOOL	Disposed();
	BOOL	IsLocked();
	VOID	CreateLock();
	VOID	RemoveLock();
	BOOL	FileExists();



private:
	BOOL	m_bDisposed;
	BOOL	m_bFileLocked;
	BOOL	m_bFileExists;

};

Open in new window


// _ScheduleFileLock.cpp : implementation file
//

#include "stdafx.h"
#include "NvlibMFC.h"
#include "_ScheduleFileLock.h"


// _ScheduleFileLock

_ScheduleFileLock::_ScheduleFileLock()
{
	m_bDisposed = FALSE;
	m_bFileExists = FALSE;
}

_ScheduleFileLock::~_ScheduleFileLock()
{

	Dispose();
}

VOID _ScheduleFileLock::Dispose()
{
	m_bDisposed = TRUE;
}

BOOL _ScheduleFileLock::Disposed()
{
	return m_bDisposed;
}

VOID _ScheduleFileLock::CreateLock()
{
	if (!FileExists())
	{
		CFile cf;
		CFileStatus cfs;
		TRY 
		{
			if (!cf.Open(_RCScheduleLock,CFile::modeCreate | CFile::modeReadWrite))
			{
				CString tmpValue;
				tmpValue= "Schedule Started.";
				cf.Write(tmpValue,tmpValue.GetLength());
				cf.Close();
			}
		}
		CATCH (CFileException, e)
		{

		}
		END_CATCH

	}
}

VOID _ScheduleFileLock::RemoveLock()
{
	if (FileExists())
	{
		CFile cf;
		TRY 
		{
			cf.Remove(_RCScheduleLock);
		}
		CATCH (CFileException, e)
		{

		}
		END_CATCH


	}
}

BOOL _ScheduleFileLock::FileExists()
{
	CFile cf;
	CFileStatus cfs;

	if (!cf.Open(_RCScheduleLock,CFile::modeCreate))
	{
		if (cf.GetStatus(cfs))
		{ // The file exists do nothing
			m_bFileExists = TRUE;
			return TRUE;
		}
	}
	return FALSE;
}

// _ScheduleFileLock member functions

Open in new window

0
Comment
Question by:TimPeer
16 Comments
 

Author Comment

by:TimPeer
ID: 35212774
If these files are included in the Main APP, the program compiles fine. No unresolved references.
0
 
LVL 11

Accepted Solution

by:
DeepuAbrahamK earned 84 total points
ID: 35212993
I can see that the destructor is already defined

_ScheduleFileLock::~_ScheduleFileLock()
{

      Dispose();
}

try removing the virtual key word and see. However this is not a solution.
0
 

Author Comment

by:TimPeer
ID: 35213005
I tried that. One of may configuration permutations. I managed to get it to work correctly by including the header and implementation in the main project. These documents were getting included / exported from a DLL.

When exporting with DUMPBIN, the dll appeared to not have any named / or ordinal reference ids. A shot in the dark here... but it would seem that maybe an old reference is getting included? I deleted / cleaned and removed all files in the bin and debug directories and checked the property pages for the DLL and the main project. It is sloppy... but if I end up calling the routine from inside the DLL I may just create another named copy of the class.

Another update: After I moved the class to the main program, another class that I was having trouble with, is now working (without any changes to the code or configuration).
0
 
LVL 40

Assisted Solution

by:evilrix
evilrix earned 83 total points
ID: 35213578
O/T but be careful when starting your symbol names with an underscore as the C++ standard reserves their use:

"Each name that contains a double underscore (_ _) or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use."

"Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace"
0
 
LVL 32

Assisted Solution

by:sarabande
sarabande earned 250 total points
ID: 35214102
when accessing a dll from an application you normally have a dll and additionally an import library. the import library usually has same name as the dll but extension .lib. it contains wrapper functions to the exported functions of the dll and so the linker would find the called symbols when you add the lib file either to the project tree or to the linker-input settings.

if the dll has no import lib you can't link it directly to your application but would load it dynamically at runtime and call the functions via function pointer. that is not a recommendable way especially when a class should be 'exported'.

note, if you developed the dll with Visual Studio you should get a import lib (or export lib from dll view) with your dll.

Sara
0
 

Author Comment

by:TimPeer
ID: 35217582
Thanks Sara and evilrix,

Regarding the DLL and export lib. VS is creating the .lib only. I added the _USRDLL preprocessor definition also.

0
 
LVL 12

Assisted Solution

by:trinitrotoluene
trinitrotoluene earned 83 total points
ID: 35221958
did u try delay loading the dll without using a lib?
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 32

Assisted Solution

by:sarabande
sarabande earned 250 total points
ID: 35222353
the expected output of a project can be seen in the project properties in the Linker section

if only a .lib was created but not a .dll i would assume the project is not the one which has created the dll file you tried to access. if you want to solve the dll issue i would suggest to start with a new dll project and move the sources from the current place to the new project folder.

the _USRDLL preprocessor macro is supposed to control  the export/import specifier in the header file of the dll. if the _USRDLL is defined, the specifiers should be __declspec(export) what is needed by the dll project for exporting its functions or classes while the absence of the _USRDLL  should generate the __declspec(import) as needed by projects which would use the dll.

Sara
0
 

Author Comment

by:TimPeer
ID: 35223276
I have not considered delay loading the dll. I will research what is needed to do this. regarding Sara's comment, I did just as you suggested as a new MFC DLL  project was created and the problematic header and implementation were moved over to it. Compiled, dll created... but continued to load specific functions in the main app resulting in unresolved references.

my project initially had a couple of .H and .CPP files containing many classes. I have since moved the classes to their respective .H and .CPP files. This last class has been a problem since.

Question: is the header information stored in files other than the .lib in VS2010? Maybe a stale reference to the file is persisting in the VS IDE?
0
 
LVL 32

Assisted Solution

by:sarabande
sarabande earned 250 total points
ID: 35225082
in you app project did you add the lib generated by the dll project at Linker - Input - Additional Dependencies?

is the path where the lib resides added to the Linker - General - Additional Library Directories ?  (alternatively you could copy the .lib in post build step to one of the known library directories).

note, the header information is (should be) only stored in the .h file of the dll project. the .lib only knows the the names (symbols). so the linker would lookup into the .obj files and .lib files 'linked' to the application project. however in c++ we have a name-mangling where the compiler adds some additionally prefix and suffix to function names to be able to have the same function name twice with different arguments. so the symbol name the linker is looking for has additional information about the argument types and return value type included which is some kind of storing header information with the function name.

the .lib file contains those functions which were specified with the __declspec(export) specifier. you may open the .lib file with a hex editor (for example in visual studio open with ...) and you should see the functions you were calling (+ the name mangling). if not, you need to look for the header file and the _USRDLL preprocessor macro or post the header file here.

Sara


 
0
 

Author Closing Comment

by:TimPeer
ID: 35479457
the responses didn't address my question. I am, however ,thankful for the response.
0
 

Author Comment

by:TimPeer
ID: 35484777
The solution provided is relevant for resolving the issue and should stand. In my case, the problem was solved with a different approach. I granted points specifically because the solution is relevant to the question irrespective of the applicability to my issue.

Please ensure these points are issued and the solution is searchable in the Knowledge-base. There are two possible solutions to my question on this kb question.

Tim
0
 
LVL 32

Expert Comment

by:sarabande
ID: 35484965
as you told the responses didn't address your q. i looked once more to your initial question and the error message you posted:

1>MyFile.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: virtual __thiscall _ScheduleFileLock::~_ScheduleFileLock(void)"


i wonder why in the error is a __declspec(dllimport) while in the class header there is no import/export specifier.

if the class (implementation) was moved to the dll and you want the dll export your class, you need to add a __declspec(dllexport) specifier to the class (statement) in the header.

in your application where you want to use the class you need a __declspec(dllimport) specifier.

to solve both with one header file you could use a preprocessor macro like

#ifdef MYDLL
#define DLL_EXPORT_IMPORT __declspec(dllexport) 
#else
#define DLL_EXPORT_IMPORT __declspec(dllimport)
#endif

DLL_EXPORT_IMPORT class _ScheduleFileLock : public CObject
{
    ...

Open in new window


in the dll project you would add MYDLL to the preprocessor macros and so the export specifier got valid. in the application project you would add no macro and so the import specifier would apply.

what i wonder is the error message which seems to imply that you already used the import specifier. i also wonder that you don't have errors for all other class member functions when you compiled the dll without an export specifier.

the only explanation i have is that the class header you posted is not the original one (what means the right one has the import/export specifiers). if that is true i would assume that you were using an older import library (file) when linking the application against the dll and this library was made before you added the destructor to the class.

Sara
0
 
LVL 32

Expert Comment

by:sarabande
ID: 35485079
as you seem to have the issue only with the virtual destructor, i checked whether it is possible to export a virtual member function of a class derived from a baseclass which comes from an imported (mfc) dll. and that is not allowed. see

http://msdn.microsoft.com/en-us/library/81h27t8c(v=vs.80).aspx

what explains your error and makes the accepted answer of DeepuAbrahamk a valid solution.

Sara
0
 

Author Comment

by:TimPeer
ID: 35486035
I didn't distribute the points on this question. The moderator did. My choice was to provide the points equally since I received feedback from many on this issue. My issue seems to have been unrelated to the question and subsequent responses and to be fair distributed the points to all with no weighting.

The site moderator seemed to have adjusted the points as he/she deemed appropriate.

Many thanks Sara, your comments were truly appreciated and I will ensure future questions are handled different regarding the issuing of points on questions.

Very best,

Tim
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now