.def Files, dll, Linking Error

Jun 1, 2011 at 10:22am
Hi all

I think that I should start this by saying that I am fairly new to C++. Currently, I can only write basic OOP programs.

However, I have been given a task at work to compile and link some old code that we have (roughly 10 years old) to produce an executable. An error is occurring at the linking stage that I cannot seem to solve.

The error messages that I am getting are similar to the one below:


Linking...
.\Reports.def(4) : warning LNK4017: DESCRIPTION statement not supported for the target platform; ignored
   Creating library .\Debug/Reports.lib and object .\Debug/Reports.exp
Reports.exp : error LNK2001: unresolved external symbol "public: bool __thiscall CReportList::ActivateDatabaseReport(unsigned short *,unsigned short *)" (?ActivateDatabaseReport@CReportList@@QAE_NPAG0@Z)
Reports.exp : error LNK2001: unresolved external symbol "public: bool __thiscall CReportList::ActivateReport(unsigned short *)" (?ActivateReport@CReportList@@QAE_NPAG@Z)
Reports.exp : error LNK2001: unresolved external symbol "public: bool __thiscall CReportList::DeactivateReport(unsigned short *)" (?DeactivateReport@CReportList@@QAE_NPAG@Z)
Reports.exp : error LNK2001: unresolved external symbol "public: bool __thiscall CReportList::get_ReportText(unsigned short *,unsigned short * *)" (?get_ReportText@CReportList@@QAE_NPAGPAPAG@Z)
.\Debug/Reports.dll : fatal error LNK1120: 4 unresolved externals
Build log was saved at "file://c:\ORH\SPARSim\SPARSim_Development_JAE\02_PoliceSimulation\Reports\Debug\BuildLog.htm"
Reports - 5 error(s), 1 warning(s)


I think that the problem might be with the file Reports.def (code below).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
; Reports.def : Declares the module parameters for the DLL.

LIBRARY      "Reports"
DESCRIPTION  'Reports Windows Dynamic Link Library'

EXPORTS
    ; Explicit exports can go here
	?ReportEventA@CReportList@@QAEXPAVCActivity@@@Z @1
	?ReportList@@YAAAVCReportList@@XZ				@2
	?ActivateReport@CReportList@@QAE_NPAG@Z			@3
	?DeactivateReport@CReportList@@QAE_NPAG@Z		@4
	?StopReporting@CReportList@@QAEXXZ				@5
	?get_ReportText@CReportList@@QAE_NPAGPAPAG@Z	@6
    ?Initialise@CReportList@@QAE_NJAAV?$vector@VCStationReportData@@V?$allocator@VCStationReportData@@@std@@@std@@@Z @7
	?ActivateDatabaseReport@CReportList@@QAE_NPAG0@Z @8


I don't know how a dll works and so have no idea what is going wrong.

Any help would be much appreciated!
Jun 2, 2011 at 12:35pm
I have now solved the problem.

The method name given in the .def file is the "decorated name" eg:

?ReportEventA@CReportList@@QAEXPAVCActivity@@@Z

The format of these decorated names has changed slightly through the versions of Visual Studio, hence why it was not working.

I used DUMPBIN to get the correct decorated name for the version of Visual Studio that I am using, amended the .def file accordingly, and it now works!

JimSim
Jun 2, 2011 at 12:41pm
You could just export the class.
Jun 2, 2011 at 3:44pm
Thanks for your reply kbw.

I had found something about using __declspec(dllexport/dllimport) , but I wasn't sure how to use this or where to put it.

For example, currently I have a line in the .def file

?ReportEventA@CReportList@@QAEXPAVCActivity@@@Z

which relates to the method ReportEvent. I have a header file (ReportList.h), which has the class definition in it:

1
2
3
4
5
6
7
8
class CReportList
{
...
public:
...
	void ReportEvent(CActivity* pActivity);
...
};


and in the ReportList.cpp file I have the full definition of the method:

1
2
3
4
5
6
7
8
9
10
void CReportList::ReportEvent(CActivity* pActivity)
{
	std::vector<CReport*>::iterator theIterator;

	for(theIterator = m_aReports.begin(); theIterator != m_aReports.end(); theIterator++)
	{
		if ((*theIterator)->IsActive() == true)
			(*theIterator)->ReportEvent(pActivity);
	}
}


If I wanted to export this method, what would I add in and where?

Thanks in advance for any help!
Jun 3, 2011 at 9:03am
The exporter of the class/function must declare it to be __declspec(dllexport). But the importer must declare it to be __declspec(dllimport).

Recent versions of the Visual Studio project wizard defined a preprocessor variable with a name based on the project name.

Let's say you create a project called utils that generates a library utils.dll. The wizard will add a preprocessor macro UTILS_EXPORTS. You can then make this sort of definition in a public header file:
1
2
3
4
5
#ifdef UTILS_EXPORTS
#define UTILS_EXPORT __declspec(dllexport)
#else
#define UTILS_EXPORT __declspec(dllimport)
#endif 

Then you can write code like:
1
2
3
4
5
6
7
8
class UTILS_EXPORT SomeClass
{
public:
    SomeClass(int somevalue);
    std::string SomeMethod() const;
};

UTILS_EXPORT std::string GetName();
Last edited on Jun 3, 2011 at 9:07am
Topic archived. No new replies allowed.