Board index » cppbuilder » Accessing class methods through DLL

Accessing class methods through DLL


2007-07-25 10:04:57 PM
cppbuilder25
I'm trying to compile this code but I get an error:
[Linker Error] Error: Unresolved external 'CStrGrid::~CStrGrid()'
referenced from Z:\CPMS\DLLS\TESTAPP\DEBUG_BUILD\UNIT1.OBJ
=========
StrGrid.h
=========
#ifndef StrGridH
#define StrGridH
#include <Grids.hpp>
class CStrGrid
{
public:
CStrGrid();
virtual ~CStrGrid();
virtual void EmptyStringGrid( TStringGrid *io_pStringGrid );
};
#endif
===========
StrGrid.cpp
===========
#include "StrGrid.h"
//---------------------------------------------------------------------------
CStrGrid::CStrGrid()
{
}
//---------------------------------------------------------------------------
CStrGrid::~CStrGrid()
{
}
//---------------------------------------------------------------------------
void CStrGrid::EmptyStringGrid( TStringGrid *io_pStringGrid )
{
// Trying to call this method
}
//---------------------------------------------------------------------------
========
Main.cpp (Main Form)
========
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h" // Added TSringGrid grdTest in header
#include "StrGrid.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
HMODULE hMod = LoadLibrary( "SomeFile.dll" );
typedef CStrGrid* ( *PFNCreate )();
PFNCreate pfnCreate =
( PFNCreate )GetProcAddress( hMod, TEXT( "CreateObjectCStrGrid" ) );
CStrGrid* grd = ( pfnCreate )();
grd->EmptyStringGrid( grdTest );
delete grd;
FreeLibrary( hMod );
}
//---------------------------------------------------------------------------
 
 

Re:Accessing class methods through DLL

"Stephane" < XXXX@XXXXX.COM >wrote in message
Quote
I'm trying to compile this code but I get an error:
That is because the header file defines a non-abstract class, so the main
project is expecting the class's implementation to be available somewhere in
the project. But you are not actually including any files into the project
that contain the actual class implementation, so the linker can't find the
code it needs, hense the error.
You can't define a class for a DLL like you are attempting to do. However,
since you are already exporting a creator function from the DLL, you need to
change the header file to define an abstract interface instead of a class,
and then have the creator function return a pointer of that interface type.
That way, the actual implementation of the object remains private to the
DLL, and the main project doesn't have to care about the actual
implementation for the object so no more linker errors occur.
In other words:
--- StrGrid.h ---
#ifndef StrGridH
#define StrGridH
#include <Grids.hpp>
#ifdef _BUILDING_DLL_
#define MYEXPORT __declspec(dllexport)
#else
#define MYEXPORT __declspec(dllimport)
#endif
class IStrGrid
{
public:
virtual void EmptyStringGrid(TStringGrid *io_pStringGrid) = 0;
};
#ifdef __cplusplus
extern "C" {
#endif
MYEXPORT IStrGrid* __stdcall CreateObjectStrGrid(void);
MYEXPORT void __stdcall FreeObjectStrGrid(IStrGrid *pStrGrid);
#ifdef __cplusplus
}
#endif
#endif
--- StrGrid.cpp ---
#define _BUILDING_DLL_
#include "StrGrid.h"
class CStrGrid : public IStrGrid
{
public:
CStrGrid();
~CStrGrid();
virtual void CStrGrid::EmptyStringGrid(TStringGrid *pStringGrid);
};
//--------------------------------------------------------------------------
-
CStrGrid::CStrGrid()
{
//...
}
//--------------------------------------------------------------------------
-
CStrGrid::~CStrGrid()
{
//...
}
//--------------------------------------------------------------------------
-
void CStrGrid::EmptyStringGrid(TStringGrid *pStringGrid)
{
//...
}
//--------------------------------------------------------------------------
-
IStrGrid* __stdcall CreateObjectStrGrid(void)
{
CStrGrid *pStrGrid;
try
{
pStrGrid = new CStrGrid;
}
catch (...)
{
pStrGrid = NULL;
}
return pStrGrid;
}
//--------------------------------------------------------------------------
-
void __stdcall FreeObjectStrGrid(IStrGrid *pStrGrid)
{
try
{
delete pStrGrid;
}
catch (...)
{
}
}
//--------------------------------------------------------------------------
-
--- Main.cpp ---
#include "StrGrid.h"
{
typedef IStrGrid* (__stdcall *PFNCreate)(void);
typedef void (__stdcall *PFNFree)(IStrGrid*);
HMODULE hMod = LoadLibrary("SomeFile.dll");
if( hMod )
{
PFNCreate pfnCreate = (PFNCreate) GetProcAddress(hMod,
TEXT("CreateObjectStrGrid"));
PFNFree pfnFree = (PFNFree) GetProcAddress(hMod,
TEXT("FreeObjectStrGrid"));
if( (pfnCreate) && (pfnFree) )
{
IStrGrid* grd = pfnCreate();
if( grd )
{
grd->EmptyStringGrid(grdTest);
pfnFree(grd);
}
}
FreeLibrary(hMod);
}
}
Gambit
 

Re:Accessing class methods through DLL

I'm sorry for not understanding your example but I can't seem to figure
out how is it not declared??? The main file includes the header and
within the header the class IStrGrd is declared???
Can you enlighten me on this matter.
Thank you very much
 

{smallsort}

Re:Accessing class methods through DLL

< XXXX@XXXXX.COM >wrote in message
Quote
I'm sorry for not understanding your example but I can't seem
to figure out how is it not declared??? The main file includes
the header and within the header the class IStrGrd is declared???
Do you have circular references in your header files? Can you show the
actual code you are using now? The code I gave you earlier works fine for
me, so it has to be an issue with the way you applied it to your code.
Gambit
 

Re:Accessing class methods through DLL

=============================================================================
StrGrid Header
-----------------------
#ifndef StrGridH
#define StrGridH
#include <Grids.hpp>
//---------------------------------------------------------------------------
#ifdef _BUILDING_DLL_
#define MYEXPORT __declspec( dllexport )
#else
#define MYEXPORT __declspec( dllimport )
#endif
class IStrGrid
{
public:
virtual void EmptyStringGrid( TStringGrid *io_pStringGrid ) = 0;
};
#ifdef __cplusplus
extern "C" {
#endif
MYEXPORT IStrGrid* __stdcall CreateObjectStrGrid( void );
MYEXPORT void __stdcall FreeObjectStrGrid( IStrGrid *pStrGrid );
#ifdef __cplusplus
}
#endif
#endif
=============================================================================
StrGrid CPP
-----------
#define _BUILDING_DLL_
#include "_class_StrGrid.h"
//---------------------------------------------------------------------------
class CStrGrid : public IStrGrid
{
public:
CStrGrid();
~CStrGrid();
virtual void CStrGrid::EmptyStringGrid( TStringGrid *pStringGrid );
};
//---------------------------------------------------------------------------
CStrGrid::CStrGrid()
{
}
//---------------------------------------------------------------------------
CStrGrid::~CStrGrid()
{
}
//---------------------------------------------------------------------------
void CStrGrid::EmptyStringGrid( TStringGrid *io_pStringGrid )
{
int iRows, iCols, iFixRows, iFixCols;
iRows = io_pStringGrid->RowCount;
iCols = io_pStringGrid->ColCount;
iFixRows = io_pStringGrid->FixedRows;
iFixCols = io_pStringGrid->FixedCols;
for( int iRowsCur = 0 + iFixRows; iRowsCur <= iRows; iRowsCur++ )
{
for( int iColsCur = 0 + iFixCols; iColsCur <= iCols; iColsCur++ )
{
io_pStringGrid->Cells[iColsCur][iRowsCur] = "";
}
}
io_pStringGrid->RowCount = 1 + iFixRows;
}
//---------------------------------------------------------------------------
IStrGrid* __stdcall CreateObjectStrGrid( void )
{
CStrGrid *pStrGrid;
try
{
pStrGrid = new CStrGrid;
}
catch ( ... )
{
pStrGrid = NULL;
}
return pStrGrid;
}
//--------------------------------------------------------------------------
void __stdcall FreeObjectStrGrid(IStrGrid *pStrGrid)
{
try
{
delete pStrGrid;
}
catch (...)
{
}
}
//--------------------------------------------------------------------------
=============================================================================
Main Form
---------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "_class_StrGrid.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
typedef IStrGrid* ( __stdcall *PFNCreate )( void );
typedef void ( __stdcall *PFNFree )( IStrGrid* );
HMODULE hMod = LoadLibrary( "SomeDLL.dll" );
if( hMod )
{
PFNCreate pfnCreate = ( PFNCreate ) GetProcAddress( hMod, TEXT(
"CreateObjectStrGrid" ) );
PFNFree pfnFree = ( PFNFree ) GetProcAddress( hMod, TEXT(
"FreeObjectStrGrid" ) );
if( ( pfnCreate ) && ( pfnFree ) )
{
IStrGrid* grd = pfnCreate();
if( grd )
{
grd->EmptyStringGrid( grdTest );
pfnFree( grd );
}
}
FreeLibrary( hMod );
}
}
//---------------------------------------------------------------------------
=============================================================================
 

Re:Accessing class methods through DLL

Quote
Can you show the actual code you are using now?
Did that... Maybe you didn't see it.
 

Re:Accessing class methods through DLL

I'm just wondering if you had found what was wrong Remy?