Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2007-11

interfaces vs classes in dll

26 messages · 12 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Mattias Gaertner

Lazarus has the IDEIntf, the API for IDE plugins.

What is better in this case: classes or interfaces? What if someday there are packages?
What if someday there is a closed source dll plugin?

Mattias

Reply by email

Marc Weustink
to Mattias Gaertner
Mattias Gaertner wrote 5 lines
Lazarus has the IDEIntf, the API for IDE plugins. What is better in this case: classes or interfaces? What if someday there are packages? What if someday there is a closed source dll plugin?

3x Interfaces (you need a shared memmanager in this case)

Additional advantage with interfaces is that you can have different versions of an interface implemented by the same class I can imagine that some interface needs to be extended someday, then adding a newer version (=copy + new guid + extention) of the interface won't break older plugins.

Marc

Reply by email

Michael Van Canneyt
to Mattias Gaertner: Lazarus has the IDEIntf, the API for IDE plugins. What is better in this case: classes or…
Mattias Gaertner wrote
Lazarus has the IDEIntf, the API for IDE plugins. What is better in this case: classes or interfaces?

Classes:
- No reference counting mess.
- Easier to grasp conceptually.
- You can use ansistrings. Interfaces require widestrings. (olestrings to be exact)

What if someday there are packages?

It'll work transparantly.

What if someday there is a closed source dll plugin?

If it is a package, there is no problem.

Michael.

Reply by email

Paul Ishenin
to Michael Van Canneyt

Michael Van Canneyt пишет:

Show quoted text 12 lines
On Thu, 29 Nov 2007, Mattias Gaertner wrote: > Lazarus has the IDEIntf, the API for IDE plugins. > > What is better in this case: classes or interfaces? > Classes: - No reference counting mess. - Easier to grasp conceptually.

In plugin dll?

- You can use ansistrings. Interfaces require widestrings. (olestrings to be exact)

Who told you this? Interface com object

Show quoted text 11 lines
> What if someday there are packages? > It'll work transparantly. > What if someday there is a closed source dll plugin? > If it is a package, there is no problem.

And even after extending class old class dependant plugins will work? How?

Best regards,
Paul Ishenin.

Reply by email

Marco van de Voort
to Michael Schnell
> What is better in this case: classes or interfaces? > What is the advantage of interfaces anyway (seems that I have been missing something ... )

A limited form of multiple inheritance.

I _thought_ it would be reference counting, but in the other thread someone wants to (and does) use Interfaces without reference counting.

No. For basic MI you don't need ref counting, since your normal object persistance takes care of that.

And note that while corba is ref counted, afaik the references are there manually instrumented. So even for remoting purposes it is not needed. It is afaik simply because that is the COM philosophy.

Reply by email

Michael Van Canneyt
to Paul Ishenin: Michael Van Canneyt пишет: In plugin dll? Who told you this? Interface com object…
Paul Ishenin wrote 15 lines
Michael Van Canneyt пишет: > On Thu, 29 Nov 2007, Mattias Gaertner wrote: > > > > Lazarus has the IDEIntf, the API for IDE plugins. > > > > What is better in this case: classes or interfaces? > > > > Classes: > - No reference counting mess. - Easier to grasp conceptually. > In plugin dll?

Sure. Why not ?
Obviously, the DLL needs to use packages, but that is understood.

> - You can use ansistrings. Interfaces require widestrings. (olestrings to be > exact) > Who told you this? Interface com object

COM has nothing to do with it.

When you pass an interface that uses ansistrings to a DLL, the ansistrings in it (or referenced by it) may be disposed of by the wrong memory manager.

Since I assume the DLL use is the scenario that is wanted, it de facto means that you must use widestrings.

The alternative is that you require that you can set the memory manager of the plugin. This, in turn, is not feasible, because some plugins will need the C memory or other memory managers. (see the whole borland sharedmm.dll mess)

In short: DLL => No ansistrings in interface.

(and guess why: reference counting, same disease as for interfaces)

Show quoted text 14 lines
> > What if someday there are packages? > > > > It'll work transparantly. > > > > What if someday there is a closed source dll plugin? > > > > If it is a package, there is no problem. > And even after extending class old class dependant plugins will work? How?

Because you use packages. A DLL will never work.

Michael.

Reply by email

Daniël Mantione
to Martin Schreiber: Please remember that widestrings on Linux *are* reference counted. I don't know about…

Op Fri, 30 Nov 2007, schreef Martin Schreiber:

Show quoted text 11 lines
On Friday 30 November 2007 10.26, Michael Van Canneyt wrote: > > When you pass an interface that uses ansistrings to a DLL, > the ansistrings in it (or referenced by it) may be disposed > of by the wrong memory manager. > > Since I assume the DLL use is the scenario that is wanted, > it de facto means that you must use widestrings. > Please remember that widestrings on Linux *are* reference counted. I don't know about other UNIX like platforms.

Most of the time people just want to pass ansi/wide strings across DLL's without operating on them. An open array of char/widechar is a comfortable mechanism to pass those strings accross DLL boundaries.

Daniël

Reply by email

Paul Ishenin
to Michael Van Canneyt: Sure. Why not ? Obviously, the DLL needs to use packages, but that is understood. COM has…
Michael Van Canneyt wrote 7 lines
>> Classes: >> - No reference counting mess. - Easier to grasp conceptually. >> > In plugin dll? Sure. Why not ? Obviously, the DLL needs to use packages, but that is understood.

I mean what is easier to grasp conceptually when you use class in dll instead of interface? I think nothing. Where is written that either we use (classes + packages) or (interfaces - packages)?

Why you should use reference counting?

Show quoted text 22 lines
>> - You can use ansistrings. Interfaces require widestrings. (olestrings to be >> exact) >> > Who told you this? Interface com object COM has nothing to do with it. When you pass an interface that uses ansistrings to a DLL, the ansistrings in it (or referenced by it) may be disposed of by the wrong memory manager. Since I assume the DLL use is the scenario that is wanted, it de facto means that you must use widestrings. The alternative is that you require that you can set the memory manager of the plugin. This, in turn, is not feasible, because some plugins will need the C memory or other memory managers. (see the whole borland sharedmm.dll mess) In short: DLL => No ansistrings in interface. (and guess why: reference counting, same disease as for interfaces)

Same misreading. Nobody written interfaces without packages. So you can use any type inside interface.

Show quoted text 12 lines
>>> What if someday there are packages? >>> >> It'll work transparantly. >> >> >>> What if someday there is a closed source dll plugin? >>> >> If it is a package, there is no problem. >> > And even after extending class old class dependant plugins will work? How? Because you use packages. A DLL will never work.

And how package system will redirect pointers from old plugin dll (which is also package) to new methods locations?

Best regards,
Paul Ishenin.

Reply by email

Graeme Geldenhuys
to Michael Schnell: What is the advantage of interfaces anyway (seems that I have been missing something ... )
Michael Schnell wrote
> What is the advantage of interfaces anyway (seems that I have been missing something ... )

Many others have answered this already, so I'm not going to type out the answer. Instead, I'll just quote some of them.... This should give you plenty of information ;-)

-------------------------

Inheritance = I am
Aggregation = I have
Interface = I can

Examples:
01: Inheritance
Both a company and a person are a legal entity. I might want to descend them both from an abstract LegalEntity class.

02: Aggregation
An employee is not a type of person. A person may perform multiple roles such as Employee, Supplier, Customer, and so on.

03: Interface
Your application may wish to access certain services such as IDataImporter, IDataExporter or IReportGenerator etc. There is no point in having these descend from a common base class at all, instead your app would just be provided with a reference to any object that implements the correct interface. This interface would then operate according to the requirements of the interface when the application executes methods of that interface. Another benefit of this is that one class might actually implement more than one interface, so it could import/export data and also generate a data
report.

Peter Morris

-------------------------
Any class, no matter in which hierarchy, can implement an interface. So your objects do not have to descend from TSomeClass to be used.

Class inheritance hierarchies are useful if you can reuse code from the base class. But if you need a capability any class in any hierarchy might have (like being printable, or being serializable, or being some kind of list, or being able to provide certain data) it makes much more sense to use interfaces.

Usually, interfaces should be very simple, only exposing a simple capability of a certain class, so it doesn't take much to implement them. But you can also think of interfaces like IList, or IEnumerable, where any class that has a list-like indexed structure, or can be enumerated, respectively, implements the appropriate interface. These classes do not have to be part of a certain hierarchy, especially if that doesn't make a lot of sense for code re-use.

Rudy Velthuis [TeamB]

-------------------------

Ah, this sample, yes. _His_ sample does not need to use interfaces or I have misunderstood how he would implement them.

I tend to avoid inheritance as much as possible. One day you'll be adding a DateOfBirth property to some class and discover that your Building class somewhere down the tree has a birthday next week :-) One big benefit of interfaces is that you are only specifying what you need from another object, the other object is free to descend from whichever class it likes.

Peter Morris

----------------------------------------

For a good tutorial about the reasons to use interfaces from an OOP point of view see this chapter of Delphi in a Nutshell by By Ray Lischner:
http://www.oreilly.com/catalog/delphi/chapter/ch02.html

In particular see this explanation:

Quoting:
"The most important use of interfaces is to separate type inheritance from class inheritance. Class inheritance is an effective tool for code reuse. A derived class easily inherits the fields, methods, and properties of a base class, and thereby avoids reimplementing common methods. In a strongly typed language, such as Delphi, the compiler treats a class as a type, and therefore class inheritance becomes synonymous with type inheritance. In the best of all possible worlds, though, types and classes are entirely separate.

Textbooks on object-oriented programming often describe an inheritance relationship as an "is-a" relationship, for example, a TSavingsAccount "is-a" TAccount. You can see the same idea in Delphi's is operator, where you test whether an Account variable is TSavingsAccount.

Outside of textbook examples, though, simple is-a relationships break down. A square is a rectangle, but that doesn't mean you want to derive TSquare from TRectangle. A rectangle is a polygon, but you probably don't want to derive TRectangle from TPolygon. Class inheritance forces a derived class to store all the fields that are declared in the base class, but in this case, the derived class doesn't need that information. A TSquare object can get away with storing a single length for all of its sides. A TRectangle object, however, must store two lengths. A TPolygon object needs to store many sides and vertices.

The solution is to separate the type inheritance (a square is a rectangle is a polygon) from class inheritance (class C inherits the fields and methods of class B, which inherits the fields and methods of class A). Use interfaces for type inheritance, so you can leave class inheritance to do what it does best: inheriting fields and methods.

In other words, ISquare inherits from IRectangle, which inherits from IPolygon. The interfaces follow the "is-a" relationship. Entirely separate from the interfaces, the class TSquare implements ISquare, IRectangle, and IPolygon. TRectangle implements IRectangle and IPolygon."

---------------------

For a good example of ref. counting interfaces you can take a look at the money.pp fpcunit example and the relative tests. fcl-fpcunit/src/exampletests/money.pp
FPCUnit can be found in the Free Pascal compiler source.

------------ END ---------------------------

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Martin Schreiber
to Michael Van Canneyt: Sure. Why not ? Obviously, the DLL needs to use packages, but that is understood. COM has…
Michael Van Canneyt wrote 8 lines
When you pass an interface that uses ansistrings to a DLL, the ansistrings in it (or referenced by it) may be disposed of by the wrong memory manager. Since I assume the DLL use is the scenario that is wanted, it de facto means that you must use widestrings.

Please remember that widestrings on Linux *are* reference counted. I don't know about other UNIX like platforms.

Martin

Reply by email

Michael Van Canneyt
to Paul Ishenin: I mean what is easier to grasp conceptually when you use class in dll instead of…
Paul Ishenin wrote 13 lines
Michael Van Canneyt wrote: > > > Classes: > > > - No reference counting mess. - Easier to grasp conceptually. > > > > > In plugin dll? > > Sure. Why not ? Obviously, the DLL needs to use packages, but that is > understood. I mean what is easier to grasp conceptually when you use class in dll instead of interface? I think nothing. Where is written that either we use (classes + packages) or (interfaces - packages)?

Because when you write "DLL", this usually means "- packages" ? I don't see the need of writing a DLL if you use packages; Better write a package instead.

Why you should use reference counting?

Because when you use interfaces, reference counting will pop up somewhere along the line to keep track of your 'live' interfaces. When a class instance is destroyed, it's destroyed...

Show quoted text 26 lines
> > > - You can use ansistrings. Interfaces require widestrings. (olestrings > > > to be > > > exact) > > > > > Who told you this? Interface com object > > COM has nothing to do with it. > > When you pass an interface that uses ansistrings to a DLL, the ansistrings > in it (or referenced by it) may be disposed of by the wrong memory manager. > > Since I assume the DLL use is the scenario that is wanted, it de facto means > that you must use widestrings. > > The alternative is that you require that you can set the memory manager > of the plugin. This, in turn, is not feasible, because some plugins will > need the C memory or other memory managers. (see the whole borland > sharedmm.dll mess) > > In short: DLL => No ansistrings in interface. > > (and guess why: reference counting, same disease as for interfaces) Same misreading. Nobody written interfaces without packages. So you can use any type inside interface.

I understand that, but if you intend to use packages, I don't see the use of interfaces. Using DLL's more or less forces the use of interfaces.

I find classes more natural than interfaces. It 'just works'. Not so with interfaces, because you must do a typecast every time.

Compare

Function GetPluginInterface : ISOmeThing;
begin
  X:=MyPluginObjectXYZ.Create;
  Result:=X as ISomething;
end;

With

Function GetPluginInterface : TSomeClass;
begin
  Result:=MyPluginObjectXYZ.Create;
end;

If you use encapsulation well, there is IMHO no reason for interfaces. I have about 2 million lines of reasonably difficult plugin code, and not a single interface in it. There is no need if you use packages.

Show quoted text 15 lines
> > > > What if someday there are packages? > > > > > > > It'll work transparantly. > > > > > > > > > > What if someday there is a closed source dll plugin? > > > > > > > If it is a package, there is no problem. > > > > > And even after extending class old class dependant plugins will work? How? > > Because you use packages. A DLL will never work. And how package system will redirect pointers from old plugin dll (which is also package) to new methods locations?

No-one. The DLL must be recompiled anyway if you use packages. And this is also true if you use interfaces, so using interfaces will not solve the problem you mention.

Michael.

Reply by email

Vincent Snijders
to Michael Van Canneyt
Michael Van Canneyt wrote 13 lines
I find classes more natural than interfaces. It 'just works'. Not so with interfaces, because you must do a typecast every time. Compare Function GetPluginInterface : ISOmeThing; begin X:=MyPluginObjectXYZ.Create; Result:=X as ISomething; end;

This is then a weakness in the language. Because MyPluginObjectXYZ implements ISOmeThing and the compiler nows that, you should be able to write just

Result := MyPluginObjectXYZ.Create;
Show quoted text 8 lines
With Function GetPluginInterface : TSomeClass; begin Result:=MyPluginObjectXYZ.Create; end;

Vincent

Reply by email

Marc Weustink
to Vincent Snijders
Vincent Snijders wrote 19 lines
Michael Van Canneyt schreef: > > I find classes more natural than interfaces. It 'just works'. Not so > with interfaces, because you must do a typecast every time. > > Compare > > Function GetPluginInterface : ISOmeThing; > > begin > X:=MyPluginObjectXYZ.Create; > Result:=X as ISomething; > end; > This is then a weakness in the language. Because MyPluginObjectXYZ implements ISOmeThing and the compiler nows that, you should be able to write just Result := MyPluginObjectXYZ.Create;

Weakness ? I do this all the time in Delphi. No need for as

Marc

Show quoted text 16 lines
> With > > Function GetPluginInterface : TSomeClass; > > begin > Result:=MyPluginObjectXYZ.Create; > end; > Vincent _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Vincent Snijders
to Marc Weustink: Weakness ? I do this all the time in Delphi. No need for as Marc
Marc Weustink wrote 23 lines
Vincent Snijders wrote: > Michael Van Canneyt schreef: >> >> I find classes more natural than interfaces. It 'just works'. Not so >> with interfaces, because you must do a typecast every time. >> >> Compare >> >> Function GetPluginInterface : ISOmeThing; >> >> begin >> X:=MyPluginObjectXYZ.Create; >> Result:=X as ISomething; >> end; >> > This is then a weakness in the language. Because MyPluginObjectXYZ > implements ISOmeThing and the compiler nows that, you should be able > to write just > > Result := MyPluginObjectXYZ.Create; Weakness ? I do this all the time in Delphi. No need for as

I took Michael's example as a requirement, not an option for extra typing :-)

Vincent

Reply by email

Paul Ishenin
to Michael Van Canneyt: Because when you write "DLL", this usually means "- packages" ? I don't see the need of…
Michael Van Canneyt wrote
No-one. The DLL must be recompiled anyway if you use packages. And this is also true if you use interfaces, so using interfaces will not solve the problem you mention.

Only if compiler (who provides package system) changed. Ide changes will not cause recompilation of plugins in case of interfaces.

Best regards,
Paul Ishenin.

Reply by email

Michael Van Canneyt
to Paul Ishenin
Paul Ishenin wrote 7 lines
Michael Van Canneyt wrote: > No-one. The DLL must be recompiled anyway if you use packages. > And this is also true if you use interfaces, so using interfaces > will not solve the problem you mention. > Only if compiler (who provides package system) changed. Ide changes will not cause recompilation of plugins in case of interfaces.

Nono. If the LCL/FCL/RTL changed or whatever, then you must recompile the DLL as well, since it uses these packages. This will IMHO be 99% of all realistic cases.

If *only* the IDE interface changed, and only that, then you are right. But in my opinion this will be less than 1% of all possible cases. So the decision to use interfaces to cover this 1% is IMHO not founded.

It's like in Delphi.
With each release and update of Delphi, you must recompile all design/runtime packages, whether the IDE interface changed or not. (and it uses interfaces too)

Michael.

Reply by email

Mattias Gaertner
to Michael Van Canneyt
Show quoted text 25 lines
On Fri, 30 Nov 2007, Paul Ishenin wrote: > Michael Van Canneyt wrote: > > No-one. The DLL must be recompiled anyway if you use packages. > > And this is also true if you use interfaces, so using interfaces > > will not solve the problem you mention. > > > Only if compiler (who provides package system) changed. Ide changes > will not cause recompilation of plugins in case of interfaces. Nono. If the LCL/FCL/RTL changed or whatever, then you must recompile the DLL as well, since it uses these packages. This will IMHO be 99% of all realistic cases. If *only* the IDE interface changed, and only that, then you are right. But in my opinion this will be less than 1% of all possible cases. So the decision to use interfaces to cover this 1% is IMHO not founded. It's like in Delphi. With each release and update of Delphi, you must recompile all design/runtime packages, whether the IDE interface changed or not. (and it uses interfaces too)

Conclusion:

A plugin without source will only work with a specific lazarus release OR if the plugin does not share any code.

A plugin with source can be simply recompiled.

Interfaces can be more flexible when extending IDE classes. At the moment there are only few classes where this makes sense. Maybe these should be changed to interfaces. But the rest can remain classes.

Correct?

Mattias

Reply by email

Michael Van Canneyt
to Mattias Gaertner
Mattias Gaertner wrote 41 lines
On Fri, 30 Nov 2007 13:22:54 +0100 (CET) Michael Van Canneyt wrote: > > > On Fri, 30 Nov 2007, Paul Ishenin wrote: > > > Michael Van Canneyt wrote: > > > No-one. The DLL must be recompiled anyway if you use packages. > > > And this is also true if you use interfaces, so using interfaces > > > will not solve the problem you mention. > > > > > Only if compiler (who provides package system) changed. Ide changes > > will not cause recompilation of plugins in case of interfaces. > > Nono. If the LCL/FCL/RTL changed or whatever, then you must recompile > the DLL as well, since it uses these packages. This will IMHO be 99% > of all realistic cases. > > If *only* the IDE interface changed, and only that, then you are > right. But in my opinion this will be less than 1% of all possible > cases. So the decision to use interfaces to cover this 1% is IMHO not > founded. > > It's like in Delphi. > With each release and update of Delphi, you must recompile all > design/runtime packages, whether the IDE interface changed or not. > (and it uses interfaces too) Conclusion: A plugin without source will only work with a specific lazarus release OR if the plugin does not share any code. A plugin with source can be simply recompiled. Interfaces can be more flexible when extending IDE classes. At the moment there are only few classes where this makes sense. Maybe these should be changed to interfaces. But the rest can remain classes. Correct?

Seems correct to me.

Whether you should actually do this change is another matter. I think there are more useful things that should be done. But you do the work, so you decide. Open source at it's best :-)

Michael.

Reply by email

Michael Schnell
to Felipe Monteiro de Carvalho
One advantage is that it can be easely used on many languages, althougth the usefulness of that for ideintf is probably very small.

I suppose you mean programming languages not spoken languages.

But Interface is a Delphi language keyword. I don't see what this has to with C or whatever.

To interface Delphi Language "Interfaces" with other programming languages additionally to the Delphi language construct a common ABI needs to be defined.

I do see that in Windows this is the case with a Delphi language "Interface" assigned to a Windows "COM" interface, which "on the other site" can have an interface to a function written in any language (as a DLL, OLE thingy or whatever). But as FP is supposed to be OS independent, the ABI between the FOP program and "the other site" needs to be done without Windows specs.

-Michael

Reply by email

Helmut Hartl
to Michael Schnell
Show quoted text 6 lines
> One advantage is that it can be easely used on many languages, > althougth the usefulness of that for ideintf is probably very small. > I suppose you mean programming languages not spoken languages. But Interface is a Delphi language keyword. I don't see what this has

to with C or whatever.

To interface Delphi Language "Interfaces" with other programming

languages additionally to the Delphi language construct a common ABI needs to be defined.

I do see that in Windows this is the case with a Delphi language

"Interface" assigned to a Windows "COM" interface, which "on the other site" can have an interface to a

function written in any language (as a DLL, OLE thingy or whatever).

But as FP is supposed to be OS independent, the ABI between the FOP program and "the other site" needs >to be done without Windows specs.

-Michael

If one speaks of "interfaces", he could also mean it in the following "computer science" relateted contexts:

http://en.wikipedia.org/wiki/Interface_%28computer_science%29

and

http://en.wikipedia.org/wiki/Design_Patterns (!)

The book about design patterns is a very valuable source of information, and a good starting point for the
"interface" concept, beside CORBA, COM and Keywords.

Software Design using interfaces provides a big chance of reusing your software, simplified tests
(by just changing the class implemting the interface) and a clearer contract between many programmers.

So the concept is also be Usable on its own without the link to CORBA, COM, OLE.

ZEOS Database Libraries are based on the GoF Design Patterns, extensively using interfaces, if someone wants
a practical implementation, that is FPC source code and not necessarely windows centric....

helmut

Reply by email