Martin Nijhoff
2008-07-07 12:45:31 UTC
Hi,
I'm not sure this is the right group for my question, so I apologize if it's
not.
A couple of years ago I wrote a number of components to handle serial
communications with devices our company makes. To get our latest software
approved for the Dutch market, all communications related code must be
separated from the rest of the code. For this purpose, I placed the
communications component in a DLL and wrote functions that encapsulate each
method of the component.
I haven't done much with DLLs in the past, so my knowledge about writing
DLLs is limited.
The communications component is called TInnova2000, which is derived from a
component called TCOMLink, which handles serial communication using certain
data frames. TCOMLink is derived from a component called TCustomCOMPort,
which handles basic serial communications. TCustomCOMPort is derived from
TComponent.
I built the DLL and used IMPLIB to generate a .lib file for the DLL. When I
add the .lib file to a new blank project and build the project, there is no
problem. But as soon as I include the .h file of the DLL, I get a linker
error message:
"[Linker Error] Undefined symbol TCustomCOMPort::~TCustomCOMPort()
__fastcall referenced from C:\Test\Main.obj".
The destructor of the TCustomCOMPort component calls the
TCustomCOMPort::Close() method to close the serial port. TCOMLink has its
own destructor to do some cleaning up. TInnova2000 doesn't have a
destructor.
Here's the code for the .cpp of the DLL (SSM32.cpp):
#include "SSM32.h"
#pragma link "SerialComm" // contains the TCustomCOMPort and TCOMLink
components.
#pragma link "Innova2000" // contains the TInnova2000 component.
TInnova2000 *Innova2000;
int WINAPI DllEntryPoint (HINSTANCE hinst, unsigned long reason, void*)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
Innova2000 = new TInnova2000(NULL);
break;
case DLL_PROCESS_DETACH:
delete Innova2000;
}
return 1;
}
bool __declspec(dllexport) Innova2000Open (int Port)
{
Innova2000->Port = Port;
return Innova2000->Open();
}
bool __declspec(dllexport) Innova2000Close ()
{
return Innova2000->Close();
}
bool __declspec(dllexport) Innova2000SetMode (TInnova2000Mode Mode)
{
return Innova2000->SetMode(Mode);
}
... and so on.
The .h for the DLL (SSM32.h) looks like this:
#include "Innova2000.h"
extern "C"
{
bool __declspec(dllexport) Innova2000Open (int Port);
bool __declspec(dllexport) Innova2000Close ();
bool __declspec(dllexport) Innova2000SetMode (TInnova2000Mode Mode);
...
}
Using TDUMP, I can see all the Innova2000... functions being exported from
the DLL. These are the only things being exported.
As far as I know, the DLL should contain all code related to the
TInnova2000, TCOMLink and TCustomCOMPort components, including the
destructor for TCustomCOMPort. Construction and destruction of the
TInnova2000 object is done inside the DLL, not in the application using the
DLL. The code 'delete Innova2000' in the DLL causes the destructor of
TCOMLink to be invoked, followed by the destructor of TCustomCOMPort.
How can I resolve the linker error? What am I doing wrong?
I'm not sure this is the right group for my question, so I apologize if it's
not.
A couple of years ago I wrote a number of components to handle serial
communications with devices our company makes. To get our latest software
approved for the Dutch market, all communications related code must be
separated from the rest of the code. For this purpose, I placed the
communications component in a DLL and wrote functions that encapsulate each
method of the component.
I haven't done much with DLLs in the past, so my knowledge about writing
DLLs is limited.
The communications component is called TInnova2000, which is derived from a
component called TCOMLink, which handles serial communication using certain
data frames. TCOMLink is derived from a component called TCustomCOMPort,
which handles basic serial communications. TCustomCOMPort is derived from
TComponent.
I built the DLL and used IMPLIB to generate a .lib file for the DLL. When I
add the .lib file to a new blank project and build the project, there is no
problem. But as soon as I include the .h file of the DLL, I get a linker
error message:
"[Linker Error] Undefined symbol TCustomCOMPort::~TCustomCOMPort()
__fastcall referenced from C:\Test\Main.obj".
The destructor of the TCustomCOMPort component calls the
TCustomCOMPort::Close() method to close the serial port. TCOMLink has its
own destructor to do some cleaning up. TInnova2000 doesn't have a
destructor.
Here's the code for the .cpp of the DLL (SSM32.cpp):
#include "SSM32.h"
#pragma link "SerialComm" // contains the TCustomCOMPort and TCOMLink
components.
#pragma link "Innova2000" // contains the TInnova2000 component.
TInnova2000 *Innova2000;
int WINAPI DllEntryPoint (HINSTANCE hinst, unsigned long reason, void*)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
Innova2000 = new TInnova2000(NULL);
break;
case DLL_PROCESS_DETACH:
delete Innova2000;
}
return 1;
}
bool __declspec(dllexport) Innova2000Open (int Port)
{
Innova2000->Port = Port;
return Innova2000->Open();
}
bool __declspec(dllexport) Innova2000Close ()
{
return Innova2000->Close();
}
bool __declspec(dllexport) Innova2000SetMode (TInnova2000Mode Mode)
{
return Innova2000->SetMode(Mode);
}
... and so on.
The .h for the DLL (SSM32.h) looks like this:
#include "Innova2000.h"
extern "C"
{
bool __declspec(dllexport) Innova2000Open (int Port);
bool __declspec(dllexport) Innova2000Close ();
bool __declspec(dllexport) Innova2000SetMode (TInnova2000Mode Mode);
...
}
Using TDUMP, I can see all the Innova2000... functions being exported from
the DLL. These are the only things being exported.
As far as I know, the DLL should contain all code related to the
TInnova2000, TCOMLink and TCustomCOMPort components, including the
destructor for TCustomCOMPort. Construction and destruction of the
TInnova2000 object is done inside the DLL, not in the application using the
DLL. The code 'delete Innova2000' in the DLL causes the destructor of
TCOMLink to be invoked, followed by the destructor of TCustomCOMPort.
How can I resolve the linker error? What am I doing wrong?