Re: Exporting Classes from DLLs
"Alex Blekhman" <tkfx.REMOVE@yahoo.com>, iletisinde sunu yazdi,
news:uCRkhCV1HHA.3548@TK2MSFTNGP04.phx.gbl...
"Mike M" wrote:
A couple of weeks ago in this newsgroup (or it may have been the
un-managed
version of this group), [...]
This is unmanaged version.
someone was asking whether they should export a
"delete" function to go along with their create function which would
create/destroy an instance of a C++ class defined by the DLL. I'm
interested
in understanding how I can use this technique.
Besides exporting a class you can make common abstract base class and
implement it inside DLL. Like this:
// Common header file (used both by DLL and EXE)
//
class ISomething
{
public:
...
virtual ~ISomething() {};
virtual int Foo(int param) = 0;
virtual void Delete() = 0;
};
// Export only one function:
//
__declspec(export/import) ISomething* CreateIt(...);
//// End of common header
// DLL implementation (.CPP file)
//
#include "Something.h"
class CSomething : public ISomething
{
public:
...
virtual int Foo(int param) { ... }
virtual void Delete() { delete this; }
};
ISomething* CreateIt(...)
{
...
return new CSomething();
}
In EXE you call `CreateIt' to get pointer to `ISomething' interface and
use it:
ISomething* pSmth = CreateIt();
int a = pSmth->Foo(42);
...
pSmth->Delete();
pSmth = NULL;
Is there a way to inject the C++ class definitions into the library
without
polluting the export list?
You could get away making `CreateIt' returning `void*', however, it's not
type safe and error prone.
Alex
Hmmm.
That's almost what I do. But I export two functions from a DLL
void* CreateObject(UINT nID);
DestroyObject(void* p);
Actually I don't use the above names. Just ordinals 1 and 2 in the export
table.
=======================
LIBRARY XXX.DLL
VERSION 1.0
EXPORTS
CreateObject @1 NONAME PRIVATE
DestroyObject @2 NONAME PRIVATE
========================
Then to load it dynamically:
========================
struct KDLL
{
HMODULE __hModule;
KDLL()
{ __hModule = 0; }
KDLL(LPCTSTR path)
{
__hModule = ::LoadLibrary(path);
}
~KDLL()
{
//fprintf(stderr, "~KDLL\n");
if (__hModule)
{
::FreeLibrary(__hModule);
__hModule = 0;
}
}
void* FindFunction(LPCTSTR name)
{
void* ret = 0;
if (__hModule)
ret = ::GetProcAddress(__hModule, name);
return ret;
}
};
struct KObjLoader : KDLL
{
typedef void* (CallType *FP_CreateObject)(uint type);
typedef void (CallType *FP_DestroyObject)(void* pObj);
FP_CreateObject __pfnCreateObject;
FP_DestroyObject __pfnDestroyObject;
KObjLoader()
{
__pfnCreateObject = 0;
__pfnDestroyObject = 0;
}
~KObjLoader()
{
//fprintf(stderr, "~KObjLoader\n");
}
KObjLoader(LPCTSTR path) : KDLL(path)
{
if (__hModule)
{
uint32 nFunc = 1;
__pfnCreateObject = (FP_CreateObject)FindFunction( (LPCSTR)nFunc );
++ nFunc;
__pfnDestroyObject = (FP_DestroyObject)FindFunction(
(LPCSTR)nFunc );
}
else
{
__pfnCreateObject = 0;
__pfnDestroyObject = 0;
}
}
void* k_CallType CreateObject(uint type)
{
return __pfnCreateObject ? __pfnCreateObject(type) : 0;
}
void CallType DestroyObject(void* pObj)
{
if (__pfnDestroyObject)
__pfnDestroyObject(pObj);
}
};
========================
I may think about your way of putting Delete inside the class.
--
Aslan