   [C++ & DLLs] Delegates across dll boundaries - help please
  Hi all,EDIT: I should say straight up that is is normal plain C++, not managed or anything like that, I use the word "delegate" in the title because it kind of describes what I am trying to do with C++.  No I can't use managed stuff, and I want to avoid third party libraries where possible because this will become part of a gina (part of windows logon) replacement product thats already live across many thousands of computers  - the fewer dependencies and unknowns the better.I was trying to keep things in a C++ kind of way (rather then C) when creating a simple event across a dll boundary.The dll handles communications between external devices, say a barcode reader.  It interprets the data back from this reader and strips off all the control characters, partial messages etc and just leaves you with a string.#ifndef IIncomingTextListener_H#define IIncomingTextListener_H#include "PeripheralCommsDll.h"class PERIPHERALCOMMS_API IIncomingTextListener{public:IIncomingTextListener(){};virtual ~IIncomingTextListener(void){};/// Called when a section of text has been read.  True to keep listening.virtual bool OnIncomingText(void* source, const char* text, const unsigned long textLength)=0;};}#endifAll one has to do is inherit from IIncomingTextListener (which seems a fair use of inheritence, as it IS a IncomingTextListener) and feed a instance of itself to a BarcodeSwipeHandler.  Both of these exist in the dll, the dll consumer creates something that implements the IIncomingTextListener interface and feeds it to an instance of BarcodeSwipeHandler, which tells it when it has any messages via OnIncomingText.This all works great, apart from by doing it like this I seem to have tied myself to linking with the lib file rather then dynamically loading with the library file.Quite rightfully if I try not to, it gives me linker errors:CGinaSwipeDlg.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: virtual __thiscall IIncomingTextListener::~IIncomingTextListener(void)" (__imp_??1IIncomingTextListener@@UAE@XZ)CGinaSwipeDlg.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) const  IIncomingTextListener::`vftable'" (__imp_??_7IIncomingTextListener@@6B@)... because I'm trying to inherit from something that's not known about at compile time.I've got factories in place that create everything else required dynamically and keep things all very OO.  But inheriting from something that's dynamically loaded via LoadLibrary?  That doesn't sound very possible to me.I like doing it the above way though because it means I'm passing around objects, rather then pointers to functions.  As far as I'm aware you can't really pass around pointers to functions of particular instances, because they don't make sense without "this".So is there another way of achieving something similar keeping things dynamically loaded in via LoadLibrary and keeping things OO?[Edited by - paulecoyote on December 8, 2005 7:01:26 AM]
  If I understand correctly, and I may not, you're trying to expose your class outside of the DLL?  I think there may be an ugly hack to do so, but DLLs are inherintly C libraries, and don't understand the concept of a class (I think, could be wrong here).  Also you're code snippet has an extra '}' before your #endif ;)Now, I don't know if this will help, but there is an article on codeproject about exporting classes without using MFC.  Code Project;  First, let me make sure I understand what you're trying to do.  You're trying to declare the IIncomingTextListener class in a DLL, and in your exe, derive a new subclass from it to feed to another class in your dll?  If you're using the same compiler for both the exe and dll, it is possible to create a shared header file between the EXE and DLL that has the IIncomingTextListener class in it and then use some sort of factory to create instances of it.  This "sorta" works when done correctly; don't expect it to work at all when the DLL and EXE are compiled with different compilers however.  In that case what you could do is something like:// This struct would be shared between the DLL and EXE via a shared header,// along with the IIncomingTextListener declarationstruct ExtTextListenerImpl{    int (*OnIncomingText)(void* ptr, void* source, const char* text, ulong length);    void (*Destroy)(void*);    void* ptr;};class ExternalIncomingTextListener : public IIncomingTextListener{public:    ExternalIncomingTextListener(ExtTextListenerImpl impl)  : impl(impl)    ~ExternalIncomingTextListener()    {  impl.Destroy(impl.ptr);    }    bool OnIncomingText(void* source, const char* text, ulong length)    {   return impl.OnIncomingText(impl.ptr, source, text, length);    }    private:    ExtTextListenerImpl impl;};You'd then write in your exe something like the following:int OnIncomingText(void* ptr, void* source, const char* text, ulong length){return reinterpret_cast<IIncomingTextListener*>    (ptr)->OnIncomingText(source,text,length);}void DestroyTextListener(void* p){    delete p;}// Assuming TextHandler is done in a somewhat similar way; this is just// an examplevoid RegisterTextListener(IIncomingTextListener* p, TextHandler* h){    ExtTextListenerImpl tl;    tl.OnIncomingText = &OnIncomingText;    tl.Destroy = &DestroyTextListener;    tl.ptr = p;    DLLRegisterTextListener(&tl, h);}// Then in the dll, you'd export a function something like the following:void DLLRegisterTextListener(ExtTextListenerImpl* tl, TextHandler* h){    // Copy the TextListener struct into the class    IIncomingTextListener l = new ExternalIncomingTextListener(*tl);    h->Add(l);}This was thrown together pretty quickly and I'm sure it can be improved on, but I hope you can pick up on what I'm trying to describe.  The basic idea is to only export pure C functions (via a struct of function pointers), but wrap it up somewhat nicely in a C++ interface. That way, the exe always makes calls to classes it creates, and same with the dll.  The destructor explictly calls a "destory" function that calls back into the exeThere is of course still a fair amount of scaffolding that needs written to make this work properly; I did some handwaving with the actual handler class, but it could work in a similar way if needed.    All this being said, I'm sure someone has a better solution (I know better solutions exist when the DLL and EXE are compiled using the same compiler).   ;  ratings+++++ for suggestions.I did think about the include file without the dllimports / dllexports define in there - but I do need cross compiler compatibility.This new thing I've written is in VC++ 2005, and the other project still is in VC++ 6 for reasons that I could go into here, but won't.  I've got to get stuff out the door pretty quick and the product is one of those "line drawn under it" things in management speak that I'm not supposed to spend too much time on it.  Bah.  Can someone tell me for sure it is compiler independant rather then depedant.  As it's just a purely abstract class (apart from the constructor and destructor) I'm not sure why it would be compiler dependant.  Comments?Desert Fox I do have factories in place to create everything that needs to be initalised on the dll side, if I used that not dll exporting things but sharing header files thing I guess that might work.  May be I should just suck-it-and-see hmm?  Want to be sure it's not dangerous to do so though.related-ish post talks about some issues with what I'm thinking of doing, as does links from here http://www.function-pointer.org/ - but not really taking in to account exporting and importing to and from dlls.Modena_au That code project article, while kind'a useful, is again about statically linking with the lib rather then completely dynamically loading things.I'm looking for an alternative but "nice" c++ way of having a class implement a function layout that's declared in the dll, which can then be used by the consuming application to create a structure / class to feed back to a function in the dll.  That can then be called in to by the dll without having to know any specifics about what it is or does, just as long as it's supporting the interface it's expecting it shouldn't care.I don't think Functors would work over a runtime loaded dll boundary either, because of the whole inheriting from a dll that isn't known about at compiletime thing.I think I've been spoilt by .Net C# class libraries to be honest.   ;  The problem in doing it in a C++ "only" way is that there is no guaranteed standard for how C++ classes are going to be laid out in memory, how their names are going to be mangled, etc.  If you compile your exe with compiler A, and then the DLL with compiler B, compilers A and B might not agree on how the virtual tables for class X are structured; so attempting to invoke a virtual method of a class defined in EXE from DLL could be catastrophic.  That's why the method of sharing a header doesn't work for cross-compiler portability.  Standard shared header method:// shared headerstruct IInterface{    virtual void foo() = 0;};DLLEXPORT void AcceptInterface(IInterface* f);// in EXEclass ConcreteClass : public IInterface{public:    void foo() {cout << "Concrete::foo" << endl;}};// in some method in EXEAcceptInterface(new ConcreteClass);// in DLLvoid AcceptInterface(IInterface* f){   f->foo(); // <-- potential BOOM!}(The other way to do this is have the DLL return an IInterface pointer if the object is created in the DLL)If the DLL and exe are compiled with different compilers, the v-table for IInterface could be different, so the DLL expects one layout, but EXE uses some other one.  The call to foo() is potentially disasterous in this situation.Hence, why in my above post I do everything via structs that just hold C function pointers and a void "implementation" pointer.  Note that all of the calls into virutal methods are then performed in the entity in which the concrete objects are created (DLL only invokes classes defined in the DLL, EXE only invokes classes defined in the EXE).  This is probably the "most C++" like solution you're going to find without sacrificing cross-compiler compatability. (Even VS6 to VS7.1 *could* cause problems, but I don't know if it actually does);  For the moment I'm staticly compiling my dll into a lib, and linking that within my app.  That way I'm not dynamically linking anything.  Seems so far that a 2005 statically compiled lib can be used with a visual c++ 6 compiled dll.   ;This old thread may be of interest.Enigma   ;  hey thanks ratings +++++   ;  As far as passing functions between DLLs in C++ goes, I've used something like this and found it works really well:#ifndef _FUNCTOR_H_#define _FUNCTOR_H_#define AUTO_FUNC( x ) ( *SmartPtrRelease<Functor*>( (x) ) )#define AUTO_FUNC_PTR( class_method, class_name, class_ptr ) ( *SmartPtrRelease<Functor*>( new FunctorPtr< class_name >( class_ptr, class_method ) ) )class Functor{public:virtual ~Functor(){}virtual voidoperator ()(void* source, const char* text, const unsigned long textLength)=0;virtual voidRelease(void) = 0;};template<class T>class FunctorPtr : public Functor{public:FunctorPtr( T *obj, void (T::*func)(void) ){ m_pObj=obj; m_pFunc=func; }void operator()( void* source, const char* text, const unsigned long textLength ) { (m_pObj->*m_pFunc)( source, text, textLength );}voidRelease(void){delete this;}protected:typedef void (T::*funcType)(void);T*m_pObj;funcTypem_pFunc;};#endif _FUNCTOR_H_// later that day, in the cpp...class foo{public:voidbar( void ){ /*stuff happens...*/}};foo f;Functor* pfunc = (Functor*)FunctorPtr<foo>( &f, bar );(*pfunc)( 0, "hello", 5 );pfunc->Release();I hope you get the idea.;Quote:Original post by BezbenAs far as passing functions between DLLs in C++ goes, I've used something like this and found it works really well:*** Source Snippet Removed ***I hope you get the idea.Hang on though, that way don't both sides of the dll have to know about both SmartPtrRelease and Functor?I take it from the lack of __dllexport as well that this is a statically linked dll rather then dynamically loaded?   