Hi,

I wonder if anyone can give me some advices for this
problem.

I have been working on some program to interface with some
devices and I would like to use the OO model to interface
with different devices with different dll.

I tried to seperate the design into 3 layers:

/* BaseDevice .h */

class EXPORT_DLL_PREFIX BaseDevice{
public:
BaseDevice(){}
~BaseDevice(){}
virtual void DeviceCallA()=0;
};

typedef BaseDevice * (CALLBACK* BASEDEVICE_GET_INSTANCE)();


/* Inherited Device class A DeviceA.cpp */
#include <BaseDevice.h>

#static BaseDevice instance = NULL;

class EXPORT_DLL_PREFIX DeviceA: BaseDevice
{
public:
DeviceA() {// do something}
~DeviceA() {// do something }
DeviceCallA()
{
// Do the actual work here...
}
};

BaseDevice * getInstance()
{
....
instance = new DeviceA();
return instance;
}



/* upper interface layer upper.cpp */
...
static BASE_DEVICE_GET_INSTANCE getInstance;

....
BaseDevice * device;
.....
getInstance = (BASE_DEVICE_GET_INSTANCE )GetProcAddress(
modHandle, _T( "getInstance" ) );
// link to the (DeviceA.dll) and get the instance...

device = getInstance();

device -> DeviceCallA();
..


Turn out it works. However, if I would like to add
another method to the BaseDevice.h for the new support
device, problems comes up. Any previous application which
was developed using DeviceA.dll will not run. I know that
it is due to the virtual table ordering when new methods
are added.

Are there any suggestion to this problem that adding new
methods will not affect previously developed applications
which used link to the previous version of the dll
implementing the previous version of the abstract class?

Thanks!

Kenric

Re: OO dll backward compactibility problem by Doug

Doug
Mon Jun 21 11:31:36 CDT 2004

Kenric Li wrote:

>Hi,
>
>I wonder if anyone can give me some advices for this
>problem.
>
>I have been working on some program to interface with some
>devices and I would like to use the OO model to interface
>with different devices with different dll.
>
>I tried to seperate the design into 3 layers:
>
>/* BaseDevice .h */
>
>class EXPORT_DLL_PREFIX BaseDevice{
>public:
> BaseDevice(){}
> ~BaseDevice(){}
> virtual void DeviceCallA()=0;
>};
>
>typedef BaseDevice * (CALLBACK* BASEDEVICE_GET_INSTANCE)();
>
>
>/* Inherited Device class A DeviceA.cpp */
>#include <BaseDevice.h>
>
>#static BaseDevice instance = NULL;
>
>class EXPORT_DLL_PREFIX DeviceA: BaseDevice
>{
>public:
> DeviceA() {// do something}
> ~DeviceA() {// do something }
> DeviceCallA()
> {
> // Do the actual work here...
> }
>};
>
>BaseDevice * getInstance()
>{
>....
>instance = new DeviceA();
>return instance;
>}
>
>
>
>/* upper interface layer upper.cpp */
>...
>static BASE_DEVICE_GET_INSTANCE getInstance;
>
>....
>BaseDevice * device;
>.....
>getInstance = (BASE_DEVICE_GET_INSTANCE )GetProcAddress(
>modHandle, _T( "getInstance" ) );
>// link to the (DeviceA.dll) and get the instance...
>
>device = getInstance();
>
>device -> DeviceCallA();
>..
>
>
>Turn out it works. However, if I would like to add
>another method to the BaseDevice.h for the new support
>device, problems comes up. Any previous application which
>was developed using DeviceA.dll will not run. I know that
>it is due to the virtual table ordering when new methods
>are added.
>
>Are there any suggestion to this problem that adding new
>methods will not affect previously developed applications
>which used link to the previous version of the dll
>implementing the previous version of the abstract class?

When you export classes in this way, you should consider your DLL equivalent
to a static library WRT programs that use it. IOW, if you add virtual
functions, or add data members, or in general do things that affect class or
vtbl layout, you must be prepared to recompile projects which use your DLL.

--
Doug Harrison
Microsoft MVP - Visual C++

Re: OO dll backward compactibility problem by anonymous

anonymous
Mon Jun 21 12:25:10 CDT 2004

Hi,

Thank you for your reply.

If I want to preserve the extendibility of the application
using OO, do you have any suggestions for me to redesign
such that any future change (i.e. new method added top the
base calss) made will not require my old application to be
recompiled?

Regards,

Kenric


>-----Original Message-----
>Kenric Li wrote:
>
>>Hi,
>>
>>I wonder if anyone can give me some advices for this
>>problem.
>>
>>I have been working on some program to interface with
some
>>devices and I would like to use the OO model to
interface
>>with different devices with different dll.
>>
>>I tried to seperate the design into 3 layers:
>>
>>/* BaseDevice .h */
>>
>>class EXPORT_DLL_PREFIX BaseDevice{
>>public:
>> BaseDevice(){}
>> ~BaseDevice(){}
>> virtual void DeviceCallA()=0;
>>};
>>
>>typedef BaseDevice * (CALLBACK* BASEDEVICE_GET_INSTANCE)
();
>>
>>
>>/* Inherited Device class A DeviceA.cpp */
>>#include <BaseDevice.h>
>>
>>#static BaseDevice instance = NULL;
>>
>>class EXPORT_DLL_PREFIX DeviceA: BaseDevice
>>{
>>public:
>> DeviceA() {// do something}
>> ~DeviceA() {// do something }
>> DeviceCallA()
>> {
>> // Do the actual work here...
>> }
>>};
>>
>>BaseDevice * getInstance()
>>{
>>....
>>instance = new DeviceA();
>>return instance;
>>}
>>
>>
>>
>>/* upper interface layer upper.cpp */
>>...
>>static BASE_DEVICE_GET_INSTANCE getInstance;
>>
>>....
>>BaseDevice * device;
>>.....
>>getInstance = (BASE_DEVICE_GET_INSTANCE )GetProcAddress(
>>modHandle, _T( "getInstance" ) );
>>// link to the (DeviceA.dll) and get the instance...
>>
>>device = getInstance();
>>
>>device -> DeviceCallA();
>>..
>>
>>
>>Turn out it works. However, if I would like to add
>>another method to the BaseDevice.h for the new support
>>device, problems comes up. Any previous application
which
>>was developed using DeviceA.dll will not run. I know
that
>>it is due to the virtual table ordering when new methods
>>are added.
>>
>>Are there any suggestion to this problem that adding new
>>methods will not affect previously developed
applications
>>which used link to the previous version of the dll
>>implementing the previous version of the abstract class?
>
>When you export classes in this way, you should consider
your DLL equivalent
>to a static library WRT programs that use it. IOW, if you
add virtual
>functions, or add data members, or in general do things
that affect class or
>vtbl layout, you must be prepared to recompile projects
which use your DLL.
>
>--
>Doug Harrison
>Microsoft MVP - Visual C++
>.
>

Re: OO dll backward compactibility problem by Igor

Igor
Thu Jun 24 13:31:03 CDT 2004

<anonymous@discussions.microsoft.com> wrote in message
news:1f6b801c457b4$b466eaf0$a401280a@phx.gbl
> If I want to preserve the extendibility of the application
> using OO, do you have any suggestions for me to redesign
> such that any future change (i.e. new method added top the
> base calss) made will not require my old application to be
> recompiled?

You can create a new abstract class Base2 derived from Base, and add new
methods to Base2. The real class will be derived from Base2 and
implement both Base and Base2 methods. The factory function still
returns Base*, so the old application happily uses unmodified Base
class, but the newer one can downcast to Base2* pointer and call new
methods.

Even better, introduce a new method at Base (so all objects implement
it) - something like

virtual void* QueryInterface(LPCSTR interfaceName);

All classes derive from Base. If they also derive from Base2 (which in
this scenario may be derived from Base or may be a standalone class),
they implement this function as

void* Derived::QueryInterface(LPCSTR interfaceName)
{
if (lstrcmpi(interfaceName, "Base2") == 0)
{
return static_cast<Base2*>(this);
}
return 0;
}

Now the client can obtain Base* pointer from the factory, then determine
at run-time if new Base2 methods are supported:

Base* pb = ...;
Base2* pb2 = (Base2*)pb->QueryInterface("Base2");
if (pb2)
{
// can call new methods
}


Of course, at this point you are essentially reinventing COM (or rather,
I'm not so subtly prodding you in the direction of COM :) ) so why not
just go all the way and make your DLL a COM server?
--
With best wishes,
Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken



Re: OO dll backward compactibility problem by Doug

Doug
Tue Jun 29 00:53:02 CDT 2004

<anonymous@discussions.microsoft.com> wrote:

>Hi,
>
>Thank you for your reply.
>
>If I want to preserve the extendibility of the application
>using OO, do you have any suggestions for me to redesign
>such that any future change (i.e. new method added top the
>base calss) made will not require my old application to be
>recompiled?

You could emulate what MS did with HWND, SendMessage, and WndProc, but
that's a lot of work and clumsy to use compared to directly using C++
classes.

--
Doug Harrison
Microsoft MVP - Visual C++