Sign in Join

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

Mailing lists / fpc-pascal / 2005-03

Re: Question about interfaces

53 messages · 16 people · –

Reply by email Subscribe to this list Your subscription

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

ml
to Nikolay Nikolov
Nikolay Nikolov wrote 8 lines
ml wrote: >btw. When writing about operators, why do they contain such little >possibilities. operator overloads could contain possibility for >['?','%','$','|','&','::','^'] > > These are C++ operators, aren't they?

Yes (some of them are, but not all), but if you think about it basic definition of operators is to make source code more easily readable.

Couldn't you imagine to use
a := b % c;
and a would actually contain real percentage??

or
s := 'Value is : ' $ CurrentValue;

and this would translate CurrentValue to currency and add to a string?

btw. and yes,:) my line of work forces me to use pascal, c#, c++, c, sql, shell and a little bit of php. So I'm forced to see the beauty and the ugly parts and features of each one. And operators are a real life saver, at least for future reading of your code (that is if they are carefully designed).

ml

_______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

ml

Just a curiosity.

1. Why does one have t specify:
type
  IMyInterface = interface
    function GetMyProp: integer;
    procedure SetMyProp(val: integer);
    property MyProp: integer read GetMyProp write SetMyProp;
  end;

As soon as you specify property in interface that costs source 1 or 2 lines of additional text. And even more when coding class that inherits interface (interface automatically demands GetMyProp and SetMyProp). Both functions will be in 99% declared in private part of the class. Besides the fact that there could be a lot of properties that wouldn't need reading or writing procedure just private variable.

Comparing to c#. c# has much more sane definition of interface. You only specify read and write. Here is the same interface in c#, notice blind get and put.

public interface IMyInterface {
int MyProp { get; set; }
}

Wouldn't it be nicer to be able specify

type
  IMyInterface = interface
    property MyProp: integer read <private> write <private>;
  end;

This would be much more flexible approach, which would not dictate two additional routines. I'm not saying that <private> is the way to go, but without specifying reading and writing subroutine.

2. Another little missing interface functionality: It would be nice if one could use reserved word is for detecting capability, for now the only way to do that is to call Supports (I think that everybody would agree that (a is IUnknown) is much nicer than Supports(a, IUnknown)), and unfortunately operator overloads for

operator is (const source: TObject; data: TGUID) dest: boolean;
operator is (const source: IUnknown; data: TGUID) dest: boolean;

just report Error: Impossible operator overload.

btw. When writing about operators, why do they contain such little possibilities. operator overloads could contain possibility for ['?','%','$','|','&','::','^']

3. This one is not some little beauty hack. So, no pressure here. But, I must admit that I'm most interested in this answer. Classes do support multiple interface inheritance, but interfaces don't. That cuts almost all of the interface flexibility. Any good reasons why?

Sincerely
ml

Reply by email

Nikolay Nikolov
to ml
ml wrote 6 lines
3. This one is not some little beauty hack. So, no pressure here. But, I must admit that I'm most interested in this answer. Classes do support multiple interface inheritance, but interfaces don't. That cuts almost all of the interface flexibility. Any good reasons why?

Probably because of Delphi and COM.

Reply by email

ml
to Nikolay Nikolov
Nikolay Nikolov wrote 10 lines
ml wrote: >3. This one is not some little beauty hack. So, no pressure here. But, I >must admit that I'm most interested in this answer. Classes do support >multiple interface inheritance, but interfaces don't. That cuts almost >all of the interface flexibility. Any good reasons why? > > Probably because of Delphi and COM.

??? You mean,... outdated technology that's ceasing to exist even on Microsoft grounds? COM will not exist anymore, and Delphi will be .net only :)

More != Less ;)

You can be backward compatible if you support more. And to cut a powerful feature? I just hope that fpc-devel team is planing to implement it.

Well, problem can be solved, but its ugly solution. Is there any way except include file to specify global macros???? Probably not:) I think I'll probably have to live with some kind of {$I
multiple_interfaces.inc} in every file. Now I wish I can do something for foreach() and world will be looking much brighter. It should be doable now that I have multiple interfaces.

Solution:

{$MACRO+}
{$define INamedList := IList, INamed, IUnique}
function SupportsInterface(aInterface: IUnknown; aGUID: array of TGUID):
boolean; // check for complete support of all passed interfaces
function SupportsInterface(aObject: TObject; aGUID: array of TGUID):
boolean; // check for complete support of all passed interfaces
type
  TGUIDArray = array of TGUID;
// Tests for detecting interface functionality
//
// and if "is" can't be assigned,...  "><" can
operator >< (const source: IUnknown; data: TGUID) dest : boolean;
operator >< (const source: IUnknown; data: TGUIDArray) dest : boolean;
operator >< (const source: TObject; data: TGUID) dest : boolean;
operator >< (const source: TObject; data: TGUIDArray) dest : boolean;
type
  TObjectCollection = class(TInterfacedObject, INamedList)
    yaddayaddayadda
  end;
begin
  if (someobjectorinterface >< [INamedList]) then
    ...
end.

Looks ugly as hell, but it does its job done with a lot of code shortage and software doesn't grow up in heights (hierarchy) but stays as low as possible, with much wider variety of combination possible

p.s. One couldn't believe how such small feature (like macro) can make your day better??? or night:)

p.p.s. fpc-devel team if anyone reads this, thanks for macros and operators. You just made one man a very happy person

ml

_______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Micha Nelissen
to ml: Yes (some of them are, but not all), but if you think about it basic definition of…
Show quoted text 8 lines
> These are C++ operators, aren't they? Yes (some of them are, but not all), but if you think about it basic definition of operators is to make source code more easily readable. Couldn't you imagine to use a := b % c; and a would actually contain real percentage??

I would read it as 'mod', because that's what means in C.

Show quoted text 10 lines
or s := 'Value is : ' $ CurrentValue; and this would translate CurrentValue to currency and add to a string? btw. and yes,:) my line of work forces me to use pascal, c#, c++, c, sql, shell and a little bit of php. So I'm forced to see the beauty and the ugly parts and features of each one. And operators are a real life saver, at least for future reading of your code (that is if they are carefully designed).

I disagree, it's not at all intuitive what the above '$' operator should mean. Is ' + CurrencyToStr(CurrentValue)' or whatever really so much to type?

Micha

Reply by email

Jonas Maebe
to ml: Yes (some of them are, but not all), but if you think about it basic definition of…
ml wrote 5 lines
btw. and yes,:) my line of work forces me to use pascal, c#, c++, c, sql, shell and a little bit of php. So I'm forced to see the beauty and the ugly parts and features of each one. And operators are a real life saver, at least for future reading of your code (that is if they are carefully designed).

Until someone else has to read your code, who attached entirely different meanings to those symbols in his own code...

Jonas

Reply by email

Bob Shaffer
to ml: Yes (some of them are, but not all), but if you think about it basic definition of…

I think I'm going to have to agree with everyone else on this one. If I read this, thinking it was pascal code, I wouldn't have the slightest idea what these % and/or $ operators were doing. Operator overloading should never be used to change the meaning of an operator. It's there so you can make existing operators work with abstract datatypes. If you save a few minutes coding things with operators that only have meaning to you, nobody else can understand what it does without a lot of extra work.

If you really want to add things like this to the language, I think that the free pascal compiler's source code is all included, written (mostly) in pascal itself, and I've heard that it's self-compilable, so you already have all the tools to develop your own extended pascal language.

ml said:

Show quoted text 30 lines
On Sat, 2005-03-19 at 01:40 +0200, Nikolay Nikolov wrote: > ml wrote: > > >btw. When writing about operators, why do they contain such little > >possibilities. operator overloads could contain possibility for > >['?','%','$','|','&','::','^'] > > > > > These are C++ operators, aren't they? Yes (some of them are, but not all), but if you think about it basic definition of operators is to make source code more easily readable. Couldn't you imagine to use a := b % c; and a would actually contain real percentage?? or s := 'Value is : ' $ CurrentValue; and this would translate CurrentValue to currency and add to a string? btw. and yes,:) my line of work forces me to use pascal, c#, c++, c, sql, shell and a little bit of php. So I'm forced to see the beauty and the ugly parts and features of each one. And operators are a real life saver, at least for future reading of your code (that is if they are carefully designed). ml

Reply by email

Jonas Raoni Soares Silva
to Jonas Maebe: Until someone else has to read your code, who attached entirely different meanings to…
Jonas Maebe wrote
Until someone else has to read your code, who attached entirely different meanings to those symbols in his own code...

I agree, pascal is one of the most clean, intuitive and easy to read languages... While updating it, the developers must keep its simplicity, or it wont be pascal anymore... Add new ideas and usable development patterns, but don't change the language concept ;]

I like both strange codes and the pascal way, in my opinion pascal should even be used instead of C on companies, since it's easier to mantain...

If you transform pascal into a c-like language, soon you'll have codes like this one that I've made in javascript, i like it, but it's a kind of write-only code... The language itself should obligate or at least help the programmer on making the right things, free-hands can make unuseful things...

getBits = function( rawData, start, length ){
if( start < 0 || length <= 0 || start + length > 8 * rawData.length )

			throw 'getBits::bits out of range';
		for( var offsetLeft, offsetRight = start % 8, curByte =

rawData.length - ( start >> 3 ) - 1, lastByte = rawData.length - -( -( start + length ) >> 3 ), diff = curByte - lastByte, sum = ( ( rawData[ curByte ] >> offsetRight ) & ( ( 1 << ( diff ? 8 - offsetRight : length ) ) - 1 ) ) + ( diff && ( offsetLeft = ( start + length ) % 8 ) ? ( rawData[ lastByte++ ] & ( ( 1 << offsetLeft ) - 1 ) ) << ( diff-- << 3 ) - offsetRight : 0 ); diff; sum += rawData[ lastByte++ ] << ( diff-- << 3 ) - offsetRight );

		return sum;
	}
"Invente, Tente!!! Faça um código eficiente" (Jonas Raoni) Jonas Raoni Soares Silva --------------------------- Desenvolvedor de aplicações jonasraoni at gmail dot com http://www.joninhas.ath.cx:666

Reply by email

Thomas Schatzl
to Michał Woźniak: Hi there. Is it possible in FPC to incorporate something like Delphi resources into the…

Hello,

Show quoted text 6 lines
Is it possible in FPC to incorporate something like Delphi resources into the compiled program? What I need is including a binary file within the executable (like when using BRCC32 and *.rc files in Delphi) so that its contents are accessible to the program at runtime, without the need to distribute those files separately.

Under Windows you can use resource files in FPC as well, just the tool to convert the .rc into a linkable binary file is called differently... See also the documentation, in particular the chapter "Using Windows resources" in prog.pdf, pg. 111ff

Regards,
Thomas

Reply by email

Michał Woźniak
to Bob Shaffer: I think I'm going to have to agree with everyone else on this one. If I read this,…

Hi there.

Is it possible in FPC to incorporate something like Delphi resources into the compiled program?
What I need is including a binary file within the executable (like when using BRCC32 and *.rc files in Delphi) so that its contents are accessible to the program at runtime, without the need to distribute those files separately.

Thanks in advance
Mike

Reply by email

Michał Woźniak
to Thomas Schatzl: Under Windows you can use resource files in FPC as well, just the tool to convert the .rc…
Show quoted text 5 lines
> Is it possible in FPC to incorporate something like Delphi resources into > the compiled program? Under Windows you can use resource files in FPC as well, just the tool to convert the .rc into a linkable binary file is called differently...

Well, actually I would need such a functionality both on Windows and Linux. I am writing a small cross-platform utility program that would need to have its, let's call it this way, "config" incroporated into the executable.

Thanks
Mike

Reply by email

Nico Aragón
to Michał Woźniak: Hi there. Is it possible in FPC to incorporate something like Delphi resources into the…
Michał Woźniak wrote 6 lines
Is it possible in FPC to incorporate something like Delphi resources into the compiled program? What I need is including a binary file within the executable (like when using BRCC32 and *.rc files in Delphi) so that its contents are accessible to the program at runtime, without the need to distribute those files separately.

IIRC, you don't even need resources:

copy /b program.exe + file.dat combined.exe

Then you can open combined.exe from itself, seek to (filelength - sizeofdatafile -1) and use blockread.

saludos, Nico Aragón

Reply by email

Michał Woźniak
to Nico Aragón
Nico Aragón wrote 6 lines
IIRC, you don't even need resources: copy /b program.exe + file.dat combined.exe Then you can open combined.exe from itself, seek to (filelength - sizeofdatafile -1) and use blockread.

Thanks, Nico!

That's exactly, what I was looking for, as I want my program to make a copy of itself, containing the additional data. Thanks a lot! :)

Cheers
Mike

Reply by email

ml
to Bob Shaffer: I think I'm going to have to agree with everyone else on this one. If I read this,…

If you would at least read original message and responded to what I asked or at least "not responded" maybe I wouldn't feel so stupid for asking my question. But hopefully this will be the last message in this thread.

Seems a bit sad to me that, I didn't get answer to "what I really asked" but a lot of flaming posts about one btw. in my question, even subject says "Question about interfaces" and not "Question about operators".

1. Couldn't interfaces support blind properties (specifying only read write capability)? Without having to specify function and procedure for writing. Property access varies from one interface inheritor to another and interface cares only about read write ability of property. Blind properties could be applied without any loosing of compatibility. And demands a whole lot more code in the way as it is applied now.

What you would get from blind interface properties?
- Lot less code.
- Smaller more readable interfaces
- freedom of property implementation in classes

2. Question about operators was about YES: "existing" and YES: "pascal standard" "is" operator and interfaces. Instead of needing to write

  if Supports(obj, ISomeInterface) then

wouldn't it be nicer to be able to write

  if (obj is ISomeInterface) then
  if (obj is [ISomeInterface, ISomeOtherInterface]) then

Which is completely what you all said. I just noted that standard pascal operator "is" does not exist for interfaces. Array checking would be nice if one uses fine grained interfaces and therefore usually needs more than one interface for one function

Other possibilities like ['?','%','$','|','&','::','^'] were only named under btw. (and how can btw. under question 2 become the main flaming topic is out of my reason, maybe its time to my annual lobotomy)

3. Interface multiple inheritance. Asking just for a reason why not, for sole curiosity. I solved that for my self with macros. Thanks to Nikolay at least I think I got that one answered (he responded with negative reason enough). And I must say that as I read his answer, I started finding the way to implement them, without bothering devel team. It is doable, ugly but doable. Just as I implemented foreach().

What are benefits of interface multiple inheritance:
- No monolithic structure
- Fine grained interfaces (smaller, easier to read)
- Lot less code duplication
- Hierarchy is lot less monolithic
- Lot more power in functionality combinations and easier determination of functionality

Bob Shaffer wrote
I think I'm going to have to agree with everyone else on this one. If I read this, thinking it was pascal code, I wouldn't have the slightest idea what these % and/or $ operators were doing. Operator overloading should

I must say I don't really bother about, but what you said is plain wrong, so I can't be quiet

That would be valid for community written projects only. So, no proprietary software exists.

Show quoted text 5 lines
never be used to change the meaning of an operator. It's there so you can make existing operators work with abstract datatypes. If you save a few minutes coding things with operators that only have meaning to you, nobody else can understand what it does without a lot of extra work.

Ever heard about documentation, and coding specifications being associated with project.

Show quoted text 5 lines
If you really want to add things like this to the language, I think that the free pascal compiler's source code is all included, written (mostly) in pascal itself, and I've heard that it's self-compilable, so you already have all the tools to develop your own extended pascal language.

Already doing that. Don't worry.

p.s. Before you try to burn heretics, at least have a reason, not a "quick doubt about heresy"

ml

Show quoted text 35 lines
ml said: > On Sat, 2005-03-19 at 01:40 +0200, Nikolay Nikolov wrote: >> ml wrote: >> >> >btw. When writing about operators, why do they contain such little >> >possibilities. operator overloads could contain possibility for >> >['?','%','$','|','&','::','^'] >> > >> > >> These are C++ operators, aren't they? > > Yes (some of them are, but not all), but if you think about it basic > definition of operators is to make source code more easily readable. > > Couldn't you imagine to use > a := b % c; > and a would actually contain real percentage?? > > or > s := 'Value is : ' $ CurrentValue; > > and this would translate CurrentValue to currency and add to a string? > > btw. and yes,:) my line of work forces me to use pascal, c#, c++, c, > sql, shell and a little bit of php. So I'm forced to see the beauty and > the ugly parts and features of each one. And operators are a real life > saver, at least for future reading of your code (that is if they are > carefully designed). > > ml > _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Nikolay Nikolov
to ml
ml wrote 5 lines
Other possibilities like ['?','%','$','|','&','::','^'] were only named under btw. (and how can btw. under question 2 become the main flaming topic is out of my reason, maybe its time to my annual lobotomy)

Well, mentioning C-isms in a pascal forum may sometimes lead to flames :) (Yes, it was a c-ism, for example operator '::' exists only in C++.) And btw some of these characters are already used in fpc. '$' is for hex values ($deadbeef), '%' - for binary (%101010) and '&' - for octal (&666). '^' is used for dereferencing pointers (p^.something := 5).

Show quoted text 8 lines
3. Interface multiple inheritance. Asking just for a reason why not, for sole curiosity. I solved that for my self with macros. Thanks to Nikolay at least I think I got that one answered (he responded with negative reason enough). And I must say that as I read his answer, I started finding the way to implement them, without bothering devel team. It is doable, ugly but doable. Just as I implemented foreach().

Keep in mind, that I'm not a FPC developer. I've just noticed that delphi compatibility is a top priority for the FPC developers, so that's why interfaces are done this way. I never said what you're asking for will never be done in the future, I just explained why is it isn't done now. When the FPC devels added interfaces, they probably added them with Delphi compatibility in mind. That would also be an answer for your question about properties in interfaces, too. Delphi 1 and 2 didn't have the VCL doesn't really rely on interfaces. Then
Delphi 3 introduced (COM) interfaces. Please note that at that time they didn't support delphi versions later, the
borland guys decided to add properties to interfaces, so you're kinda lucky that there are properties in interfaces at all :)

Reply by email

ml
to Nikolay Nikolov
Nikolay Nikolov wrote 13 lines
ml wrote: >Other possibilities like ['?','%','$','|','&','::','^'] were only named >under btw. (and how can btw. under question 2 become the main flaming >topic is out of my reason, maybe its time to my annual lobotomy) > > Well, mentioning C-isms in a pascal forum may sometimes lead to flames :) (Yes, it was a c-ism, for example operator '::' exists only in C++.) And btw some of these characters are already used in fpc. '$' is for hex values ($deadbeef), '%' - for binary (%101010) and '&' - for octal (&666). '^' is used for dereferencing pointers (p^.something := 5).

:) %$& you're right.

But you're wrong for '::' '::' exists in perl too. Other C operator is '|' (again this one exists in perl) which is or in C. But then again someone could say that both are a nice way to express delimiters.

I'm not really much of pascal lover, I'm just practical. I just use something when it is clean, logical and usable for the purpose. So if that's the case as you described it (about c flames), then either pascal has no future, or it is very very dark. Because not even one tool is not usable for all purposes.

Show quoted text 21 lines
>3. Interface multiple inheritance. Asking just for a reason why not, for >sole curiosity. I solved that for my self with macros. Thanks to Nikolay >at least I think I got that one answered (he responded with negative >reason enough). And I must say that as I read his answer, I started >finding the way to implement them, without bothering devel team. It is >doable, ugly but doable. Just as I implemented foreach(). > > Keep in mind, that I'm not a FPC developer. I've just noticed that delphi compatibility is a top priority for the FPC developers, so that's why interfaces are done this way. I never said what you're asking for will never be done in the future, I just explained why is it isn't done now. When the FPC devels added interfaces, they probably added them with Delphi compatibility in mind. That would also be an answer for your question about properties in interfaces, too. Delphi 1 and 2 didn't have the VCL doesn't really rely on interfaces. Then Delphi 3 introduced (COM) interfaces. Please note that at that time they didn't support delphi versions later, the borland guys decided to add properties to interfaces, so you're kinda lucky that there are properties in interfaces at all :)

Yep, and I thanked you for that. Yours was the only usable reply all others were just a bunch of flaming without knowing the question (as soon as I read it I started looking for some other solution). Thanks again.

ml

_______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Marco van de Voort
to ml: If you would at least read original message and responded to what I asked or at least…
Show quoted text 15 lines
Seems a bit sad to me that, I didn't get answer to "what I really asked" but a lot of flaming posts about one btw. in my question, even subject says "Question about interfaces" and not "Question about operators". 1. Couldn't interfaces support blind properties (specifying only read write capability)? Without having to specify function and procedure for writing. Property access varies from one interface inheritor to another and interface cares only about read write ability of property. Blind properties could be applied without any loosing of compatibility. And demands a whole lot more code in the way as it is applied now. What you would get from blind interface properties? - Lot less code. - Smaller more readable interfaces - freedom of property implementation in classes

This doesn't sound bad, but there is an implementation problem I think. The idea itself is sound, an interface is a contract only and how a property is implemented is a implementation detail.

However the problem is that one must be able to access the property give only the interface definition. Keep in mind that a property can be both a field and calls to getter/setter functions, and also that a property is only a language construction. In the final code, a direct reference to the field or getter/setter is done.

In this light, decoupling a property poses a problem; if the compiler has

var x : ISomeinterface; // has a  blind property someproperty
begin
  x:=getintfromsomewhere;
  writeln(x.someproperty);
end;

how do I know what code to generate for the property?

Show quoted text 9 lines
2. Question about operators was about YES: "existing" and YES: "pascal standard" "is" operator and interfaces. Instead of needing to write if Supports(obj, ISomeInterface) then wouldn't it be nicer to be able to write if (obj is ISomeInterface) then if (obj is [ISomeInterface, ISomeOtherInterface]) then

I have no idea, but I fail to see the point a bit (this isn't a much used construct), but it could.

Being a compiler developer is not sitting on a table and thinking up all kinds of interesting new extensions. I know some of the perl/python freaks seem to do it like that, but they seem to be engaged into some who can write the shortest and most unreadable code contest.

In seven years of FPC work, I pretty much came up with one extension (properties at the procedural level, and while useful, not the most interesting or timesaving one.)

Which is completely what you all said. I just noted that standard pascal operator "is" does not exist for interfaces.

There is no such thing "is" is a Delphi extension. A later one even.

Array checking would be nice if one uses fine grained interfaces and therefore usually needs more than one interface for one function

It's a set.

3. Interface multiple inheritance. Asking just for a reason why not, for sole curiosity.

Interfaces to my knowledge are contracts about sets of calls. More or less function X is at offset y*4 or something like that.

If you create a new interface by multiple inheritance from both X and Y each with 4 methods, you get a new interface Z with 8 methods.

However Z can only be compatible with one interface, namely the one that gets the first 4 methods. So if I create Z with first the 4 methods of X and then those of Y, Z will be compatible with X (same 4 methods on the same offsets), but not with Y.

I solved that for my self with macros.

Macro's are no solution, but a hack.

Just as I implemented foreach().

Eeeuw :_)

What are benefits of interface multiple inheritance: - No monolithic structure - Fine grained interfaces (smaller, easier to read) - Lot less code duplication

All a bit vague. Could you back these up with real examples?

(p.s. Interfaces have no code. That is pretty much their definition :_)

Reply by email

Michael Van Canneyt
to ml: :) %$& you're right. But you're wrong for '::' '::' exists in perl too. Other C operator…
ml wrote 26 lines
On Sun, 2005-03-20 at 02:55 +0200, Nikolay Nikolov wrote: > ml wrote: > > >Other possibilities like ['?','%','$','|','&','::','^'] were only named > >under btw. (and how can btw. under question 2 become the main flaming > >topic is out of my reason, maybe its time to my annual lobotomy) > > > > > Well, mentioning C-isms in a pascal forum may sometimes lead to flames > :) (Yes, it was a c-ism, for example operator '::' exists only in C++.) > And btw some of these characters are already used in fpc. '$' is for hex > values ($deadbeef), '%' - for binary (%101010) and '&' - for octal > (&666). '^' is used for dereferencing pointers (p^.something := 5). > :) %$& you're right. But you're wrong for '::' '::' exists in perl too. Other C operator is '|' (again this one exists in perl) which is or in C. But then again someone could say that both are a nice way to express delimiters. I'm not really much of pascal lover, I'm just practical. I just use something when it is clean, logical and usable for the purpose. So if that's the case as you described it (about c flames), then either pascal has no future, or it is very very dark. Because not even one tool is not usable for all purposes.

This is correct.
In true Unix philosphy, I also use the tool I think fits the job best. This may or may not be Pascal.

But look at it like this:
Chess has a set of limited and strict rules which are not subject to change. Grand masters think of incredibly complicated and sometimes beautiful strategies, but they stay within these limited rules.

A grand programmer uses the tools he has to make great software. As a grand master in chess does not need to change the rules, the grand programmer doesn't need to change his tools to make great software.

Which doesn't mean he could try, of course...

Michael.

Reply by email

Unknown author

How did you define ExeFile ?

Micha? Wo?niak wrote the following on 20/03/05 11:37:32:

Show quoted text 41 lines
Dnia sobota, 19 marca 2005 23:31, Nico Aragón napisał: > IIRC, you don't even need resources: > > copy /b program.exe + file.dat combined.exe > > Then you can open combined.exe from itself, seek to (filelength - > sizeofdatafile -1) and use blockread. Uhmm... I get a Runtime error 026 everytime I try to open the executable for reading from within itself. Here's the code: try writeln('Assigning file "' + ParamStr(0) + '".'); Assign(ExeFile, ParamStr(0)); writeln('Reseting...'); Reset(ExeFile); // <- ERROR HERE writeln('Seeking...'); Seek(ExeFile,FileSize(ExeFile)-14); except on E:Exception do begin writeln('Exception: ' + E.Message); halt; end; end; Am I missing something? TIA Mike _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Florian Klaempfl
to Michael Van Canneyt: This is correct. In true Unix philosphy, I also use the tool I think fits the job best.…
Michael Van Canneyt wrote 50 lines
On Sun, 20 Mar 2005, ml wrote: >On Sun, 2005-03-20 at 02:55 +0200, Nikolay Nikolov wrote: > >>ml wrote: >> >> >>>Other possibilities like ['?','%','$','|','&','::','^'] were only named >>>under btw. (and how can btw. under question 2 become the main flaming >>>topic is out of my reason, maybe its time to my annual lobotomy) >>> >>> >> >>Well, mentioning C-isms in a pascal forum may sometimes lead to flames >>:) (Yes, it was a c-ism, for example operator '::' exists only in C++.) >>And btw some of these characters are already used in fpc. '$' is for hex >>values ($deadbeef), '%' - for binary (%101010) and '&' - for octal >>(&666). '^' is used for dereferencing pointers (p^.something := 5). >> > >:) %$& you're right. > >But you're wrong for '::' '::' exists in perl too. Other C operator is >'|' (again this one exists in perl) which is or in C. But then again >someone could say that both are a nice way to express delimiters. > >I'm not really much of pascal lover, I'm just practical. I just use >something when it is clean, logical and usable for the purpose. So if >that's the case as you described it (about c flames), then either pascal >has no future, or it is very very dark. Because not even one tool is not >usable for all purposes. This is correct. In true Unix philosphy, I also use the tool I think fits the job best. This may or may not be Pascal. But look at it like this: Chess has a set of limited and strict rules which are not subject to change. Grand masters think of incredibly complicated and sometimes beautiful strategies, but they stay within these limited rules. A grand programmer uses the tools he has to make great software. As a grand master in chess does not need to change the rules, the grand programmer doesn't need to change his tools to make great software. Which doesn't mean he could try, of course...

Indeed, Bobby Fischer tried so :)

Reply by email

Michał Woźniak
to Michał Woźniak: Thanks, Nico! That's exactly, what I was looking for, as I want my program to make a copy…
Nico Aragón wrote 6 lines
IIRC, you don't even need resources: copy /b program.exe + file.dat combined.exe Then you can open combined.exe from itself, seek to (filelength - sizeofdatafile -1) and use blockread.

Uhmm... I get a Runtime error 026 everytime I try to open the executable for reading from within itself. Here's the code:

try
    writeln('Assigning file "' + ParamStr(0) + '".');
    Assign(ExeFile, ParamStr(0));
    writeln('Reseting...');
    Reset(ExeFile); // <- ERROR HERE
    writeln('Seeking...');
    Seek(ExeFile,FileSize(ExeFile)-14);
  except
    on E:Exception do
    begin
      writeln('Exception: ' + E.Message);
      halt;
    end;
  end;

Am I missing something?

TIA
Mike

Reply by email

Marco van de Voort
to Michał Woźniak

[ Charset UTF-8 unsupported, converting... ]

Show quoted text 10 lines
Dnia sobota, 19 marca 2005 23:31, Nico Arag?n napisa?: > IIRC, you don't even need resources: > > copy /b program.exe + file.dat combined.exe > > Then you can open combined.exe from itself, seek to (filelength - > sizeofdatafile -1) and use blockread. Uhmm... I get a Runtime error 026 everytime I try to open the executable for reading from within itself. Here's the code:

Known windows problem. Windows lock all .exe's.

Keep in mind that reset is actually read/write.

Try :

- Before the reset, add filemode:=0;
- change the reset to reset(exefile,1); since I doubt you want to access it in 128 bytes units.

Reply by email

Michał Woźniak
to Marco van de Voort
Show quoted text 12 lines
> Dnia sobota, 19 marca 2005 23:31, Nico Arag?n napisa?: > > IIRC, you don't even need resources: > > > > copy /b program.exe + file.dat combined.exe > > > > Then you can open combined.exe from itself, seek to (filelength - > > sizeofdatafile -1) and use blockread. > > Uhmm... I get a Runtime error 026 everytime I try to open the executable > for reading from within itself. Here's the code: Known windows problem. Windows lock all .exe's.

Nope - it's under Linux. :)

Show quoted text 7 lines
Keep in mind that reset is actually read/write. Try : - Before the reset, add filemode:=0; - change the reset to reset(exefile,1); since I doubt you want to access it in 128 bytes units.

ExeFile is defined as File of byte, therefore the file is already accessed in 1-byte units.

FileMode solved the problem. Thanks.

Cheers
Mike

Reply by email

Michael Van Canneyt
to Florian Klaempfl: Indeed, Bobby Fischer tried so :)
Florian Klaempfl wrote 14 lines
> This is correct. In true Unix philosphy, I also use the tool I think fits > the job best. > This may or may not be Pascal. > > But look at it like this: Chess has a set of limited and strict rules > which are not subject to change. Grand masters think of incredibly > complicated and sometimes beautiful strategies, but they stay within > these limited rules. > A grand programmer uses the tools he has to make great software. As a > grand master in chess does not need to change the rules, the grand > programmer doesn't need to change his tools to make great software. > Which doesn't mean he could try, of course... Indeed, Bobby Fischer tried so :)

... and look what became of him...

Michael.

Reply by email

Unknown author
to Marco van de Voort: This doesn't sound bad, but there is an implementation problem I think. The idea itself…

Quoting Marco van de Voort :

Show quoted text 37 lines
> Seems a bit sad to me that, I didn't get answer to "what I really asked" > but a lot of flaming posts about one btw. in my question, even subject > says "Question about interfaces" and not "Question about operators". > > 1. Couldn't interfaces support blind properties (specifying only read > write capability)? Without having to specify function and procedure for > writing. Property access varies from one interface inheritor to another > and interface cares only about read write ability of property. Blind > properties could be applied without any loosing of compatibility. And > demands a whole lot more code in the way as it is applied now. > > What you would get from blind interface properties? > - Lot less code. > - Smaller more readable interfaces > - freedom of property implementation in classes This doesn't sound bad, but there is an implementation problem I think. The idea itself is sound, an interface is a contract only and how a property is implemented is a implementation detail. However the problem is that one must be able to access the property give only the interface definition. Keep in mind that a property can be both a field and calls to getter/setter functions, and also that a property is only a language construction. In the final code, a direct reference to the field or getter/setter is done. In this light, decoupling a property poses a problem; if the compiler has var x : ISomeinterface; // has a blind property someproperty begin x:=getintfromsomewhere; writeln(x.someproperty); end; how do I know what code to generate for the property?

Shouldn't direct access to object and resolving object property be involved here when dealing with interface property and not pointing to interface functions and procedures?
You have the pointer to object, so you have the pointer to its vmt. Shouldn't property be accessed like that in the real world?

Show quoted text 13 lines
> 2. Question about operators was about YES: "existing" and YES: "pascal > standard" "is" operator and interfaces. Instead of needing to write > > if Supports(obj, ISomeInterface) then > > wouldn't it be nicer to be able to write > > if (obj is ISomeInterface) then > if (obj is [ISomeInterface, ISomeOtherInterface]) then I have no idea, but I fail to see the point a bit (this isn't a much used construct), but it could.

It can't be if it is not present

Show quoted text 5 lines
Being a compiler developer is not sitting on a table and thinking up all kinds of interesting new extensions. I know some of the perl/python freaks seem to do it like that, but they seem to be engaged into some who can write the shortest and most unreadable code contest.

Not that I try to lower your status or status of fpc, I repect everybody that is able to maintain project as large as this, but

Not always, if competing who will do more then yes. But then there could be a lot of good new things suggested. Users can have good ideas, look at inkscape for example.
Every suggested idea (people in mailing lists suggest different variantions or ) goes to discussion and they discuss if feature should be included and how it should be included.

I don't believe that living under borland shell is the way to go. This said is just like you would said that there's no world beside borland and all features not implemented in borland are not good.

No invention, no progress. Maybe that's why Phyton has so many people. Because people expect new approaches

Show quoted text 14 lines
In seven years of FPC work, I pretty much came up with one extension (properties at the procedural level, and while useful, not the most interesting or timesaving one.) > Which is completely what you all said. I just noted that standard pascal > operator "is" does not exist for interfaces. There is no such thing "is" is a Delphi extension. A later one even. > Array checking would be > nice if one uses fine grained interfaces and therefore usually needs > more than one interface for one function It's a set.

Ok

Show quoted text 15 lines
> 3. Interface multiple inheritance. Asking just for a reason why not, for > sole curiosity. Interfaces to my knowledge are contracts about sets of calls. More or less function X is at offset y*4 or something like that. If you create a new interface by multiple inheritance from both X and Y each with 4 methods, you get a new interface Z with 8 methods. However Z can only be compatible with one interface, namely the one that gets the first 4 methods. So if I create Z with first the 4 methods of X and then those of Y, Z will be compatible with X (same 4 methods on the same offsets), but not with Y.
Care to explain offsets here:
IA = interface
function A: integer;
end;
IB=interface(IA)
function B: integer;
end;
IC=interface(IB)
procedure C;
end;

Don't take it so literaly. It's just that interface usage goes beyond simple logic. You have two possible implementation

- monolithic structure where interfaces express most of the object reflection
- non-monolithic fine grained, which can be implemented in two ways

1. Real, interfaces that have multiple inheritors can be inherited
2. Posibility of setting sets of combinations

Version 1 would be best, but as I saw version 2 is not so bad. When you use fine grained interfaces, you try to avoid interface inheriting completely (it would not make sense anyway). And use those sets in classes inheritance and functionality checking only.

On of my previous e-mails had simple macro solution which is more than satisfiable for version 2, except that its a hack and no solution

> I solved that for my self with macros. Macro's are no solution, but a hack.

Yeah, but comparing working hacked solution to no solution...

> Just as I implemented foreach(). Eeeuw :_)

I thought that at first too, yes. But after a while I started loving them. Working with 20-30 threads does that to you.

If foreach is carefuly designed then it can be threadsafe and balanced. Which you can't say for "for i := 0 to (Count - 1) do" if you code threaded environment. Balanced enumerators reflect on changes in list. When my list deletes items in one thread all enumerators reflect to change and reposition them self accordingly.

and foreach was nothing but a beauty hack
{$define foreach := while MACRO_FOR_EACH}

but I can't afford instability. I can afford slowness, but instability no.

Show quoted text 8 lines
> What are benefits of interface multiple inheritance: > - No monolithic structure > - Fine grained interfaces (smaller, easier to read) > - Lot less code duplication All a bit vague. Could you back these up with real examples?

ok, here it one in c#, the only problem here could be that you would try to look at this from monolithic perspective. And notice how many times one could reuse those simple interfaces.
As soon as interface goes complex,... well there's no difference if you would use class.

interface ICountable{
int Count { get; put; }
}

interface IAccessible{

	int Get(int aIdx; ref object aObject);

}

interface IRemovable{

	int RemoveAt(int aIdx);

}

interface IModifiable{
	int Add(string aStr);
	int Modify(int aIdx, object aObject);
}

interface IExportable{

	int Export(int aIdx, object aObject);

}

....

interface IMyList(ICountable, IRemovable, IModifiable, IAccessible) {}

interface IMyExportable(ICountable, IAccesible, IExportable) {}

class MyList(IMyList) { ..... }
class MyExportable(IMyExportable) { ..... }

.....
int GetCountOf(object aObject) { // nothing special here isn't it. But then again this function will be usable for everything I throw at it not just the code if (aObject != null)
if (aObject is ICountable)

			return (aObject as ICountable).Count;
	return 0;

}

.... // somewhere else where my needs depend on bigger compatibility int AddStr(str aStr, object aObject) {
if (aObject is IMyList)

		(aObject as IMyList).Add(aStr);

}

Here is a simple example of having fine grained interfaces. Both object completely non-interferring one with the other (not the same hierarchy). But still I can detect wheter passed object supports counting or accessing items inside of my code.
If passed object supports ICountable then, ... well access trough ICountable(passedobject).Count and so on. But the problem with fine grained interfaces
is that you almost always need more than one interface, you can land with bunch of interfaces in declaration and supporting checks. That's why multiple interfaces are usable.
In my case I only needed to specify IMyList and IMyExportable.

Coding with fine grained Interfaces is slower than coding with objects, but it is less dependent and probably bulletproof. Difference between one and the other type of coding is
how much planning you need to do in the begining.

Its just like glade or delphi interface designer. Glade is harder to figure out but its bulletproof, while delphi is simple but at the same time almost unqualified for its existance.
I just change font size and almost all delphi windows go broken (change the language, well how many labels gets too long and get covered up with controls). Glade does not
suffer from this effects, form is always as it should be. But it had to be planned much more than delphi form was.

IMyList simplified my task, and this couldn't be done in monolithic interface. I would have to inherit ICountable in IAccessible, IAccessible in IRemovable. Which would lead that instead of having simple IModifiable, IModifiable would contain bunch of declarations which mostly wouldn't be needed. While in multiple inheritance
having separate IModifiable is possible. And reuse same IRemovable in lists, windows,... whatever. And when I need complete IMyList functionality I don't need to check for every interface just IMyList

Hope this was enough extensive

(p.s. Interfaces have no code. That is pretty much their definition :_)

???? And the reason for my asking about blind properties would be probably because I don't know that

ml

And by the way, about chess example that was here

One guy didn't succed and this is the reason why no one should try something new ever again??? Shouldn't everybody make suicide too, just because one guy didn't succed in his life, nobody will?

Show quoted text 6 lines
_______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

---------------------------------------------------------------------- This mail sent through Horde-Toaster (http://qmailtoaster.clikka.com/)

Reply by email

Marco van de Voort
to Unknown author
Show quoted text 15 lines
Quoting Marco van de Voort : > begin > x:=getintfromsomewhere; > writeln(x.someproperty); > end; > > how do I know what code to generate for the property? > Shouldn't direct access to object and resolving object property be involved here when dealing with interface property and not pointing to interface functions and procedures? You have the pointer to object, so you have the pointer to its vmt

Afaik not, you have a pointer to an interface table, And even if you can get to the object vmt from there, you don't know anything about it. interface is all about information hiding. It might not even be a proper Pascal object.

Shouldn't property be accessed like that in the real world?

No, the whole idea of property is simply to easily declare iDE editable values. As nice added extra: the ability to change from direct field to getter/setter based access easily. (read: without changes in the calling code)

Show quoted text 13 lines
> Being a compiler developer is not sitting on a table and thinking up all > kinds of interesting new extensions. I know some of the perl/python freaks > seem to do it like that, but they seem to be engaged into some who can > write the shortest and most unreadable code contest. Not that I try to lower your status or status of fpc, I repect everybody that is able to maintain project as large as this, but Not always, if competing who will do more then yes. But then there could be a lot of good new things suggested. Users can have good ideas, look at inkscape for example. Every suggested idea (people in mailing lists suggest different variantions or ) goes to discussion and they discuss if feature should be included and how it should be included.

Yes, that's what that is? And of course a feature is not auto included up front, and all sides have to be carefully weighted. Moreover, in a compiled language, there is much less possible.

I don't believe that living under borland shell is the way to go. This said is just like you would said that there's no world beside borland and all features not implemented in borland are not good.

The accent is Borland. Other features are added on merits, and they have to be real added value, not just a shorter notation, or something depending on personal taste.

No invention, no progress. Maybe that's why Phyton has so many people. Because people expect new approaches

Nonsense. Python and perl etc were launched in the bubble era and are still floating on that capital. However there is a lot of hype and tinkering,and little real work done in it. Of course, enough hype will ensure that some stuff will be done, but I don't really have the feeling that the hype and actual serious use are in any sane proportion.

Show quoted text 16 lines
> However Z can only be compatible with one interface, namely the one that > gets the first 4 methods. So if I create Z with first the 4 methods of X > and then those of Y, Z will be compatible with X (same 4 methods on the same > offsets), but not with Y. > Care to explain offsets here: IA = interface function A: integer; end; IB=interface(IA) function B: integer; end; IC=interface(IB) procedure C; end;

A 0
--- in IA only this is visible
B 4
-- in IB only this is visible
C 8

Now go to the MI example,� assume that C inherits from both IA and IB, and IB not from iA

IA:
A 0

IB:
B 0

IC: ?

Show quoted text 16 lines
Don't take it so literaly. It's just that interface usage goes beyond simple logic. You have two possible implementation - monolithic structure where interfaces express most of the object reflection - non-monolithic fine grained, which can be implemented in two ways 1. Real, interfaces that have multiple inheritors can be inherited 2. Posibility of setting sets of combinations Version 1 would be best, but as I saw version 2 is not so bad. When you use fine grained interfaces, you try to avoid interface inheriting completely (it would not make sense anyway). And use those sets in classes inheritance and functionality checking only. On of my previous e-mails had simple macro solution which is more than satisfiable for version 2, except that its a hack and no solution

Still no idea what so ever. What can you do ?

Show quoted text 6 lines
> > Just as I implemented foreach(). > > Eeeuw :_) I thought that at first too, yes. But after a while I started loving them. Working with 20-30 threads does that to you.

Do that everyday, never missed foreach.

Show quoted text 5 lines
If foreach is carefuly designed then it can be threadsafe and balanced. Which you can't say for "for i := 0 to (Count - 1) do" if you code threaded environment. Balanced enumerators reflect on changes in list. When my list deletes items in one thread all enumerators reflect to change and reposition them self accordingly.

So in short you say you use iterators on one spot. Mmany languages have iterator systems, but most don't have the silly syntactic sugar foreach.

So in your case it is only short for

x:=startiter;
while x,iterateover do y;
Show quoted text 6 lines
> All a bit vague. Could you back these up with real examples? ok, here it one in c#, the only problem here could be that you would try to look at this from monolithic perspective. And notice how many times one could reuse those simple interfaces. As soon as interface goes complex,... well there's no difference if you would use class.

So again it is actually only a shorthand notation for something that can be done perfectly otherwise. (Write them out, and test all interfaces)

One can think up a terse short notation for _every_ construct there is, that _somebody_ uses a lot, but it will only blow up language and runtime, and eat up developer time.

To give you an counter example: Personally the only thing currently on my wishlist are generics. But that is a bit too hefty to implement shortterm.

Why generics? They really allow things that can't be done:
- typesafe containers.
- parameterising algoratims with types in general.

Show quoted text 8 lines
Its just like glade or delphi interface designer. Glade is harder to figure out but its bulletproof, while delphi is simple but at the same time almost unqualified for its existance. I just change font size and almost all delphi windows go broken (change the language, well how many labels gets too long and get covered up with controls). Glade does not suffer from this effects, form is always as it should be. But it had to be planned much more than delphi form was.

It is also significantly more heavy weight. That is not necessarily bad, it is just what you choose for. Delphi has enough room to implement frameworks on top of it. And not only for this solution. Moreover one can take over the designer via the toolsapi without access to delphi.

Show quoted text 5 lines
And by the way, about chess example that was here One guy didn't succed and this is the reason why no one should try something new ever again??? Shouldn't everybody make suicide too, just because one guy didn't succed in his life, nobody will?

It will be interesting to see your patches then. Maybe I'll change my opinion if I have played with your fork of the code.

Reply by email

Unknown author
to Marco van de Voort

Quoting Marco van de Voort :

Show quoted text 10 lines
Afaik not, you have a pointer to an interface table, And even if you can get to the object vmt from there, you don't know anything about it. interface is all about information hiding. It might not even be a proper Pascal object. No, the whole idea of property is simply to easily declare iDE editable values. As nice added extra: the ability to change from direct field to getter/setter based access easily. (read: without changes in the calling code)

Could you explain this extra a little more?
Hope its not connected to lazarus. I don't use it. If it is then I don't need explanation.

Show quoted text 5 lines
Yes, that's what that is? And of course a feature is not auto included up front, and all sides have to be carefully weighted. Moreover, in a compiled language, there is much less possible.

Agreed.

Show quoted text 7 lines
Nonsense. Python and perl etc were launched in the bubble era and are still floating on that capital. However there is a lot of hype and tinkering,and little real work done in it. Of course, enough hype will ensure that some stuff will be done, but I don't really have the feeling that the hype and actual serious use are in any sane proportion.

Little work? Guess we live in different world

Show quoted text 17 lines
A 0 --- in IA only this is visible B 4 -- in IB only this is visible C 8 Now go to the MI example, assume that C inherits from both IA and IB, and IB not from iA IA: A 0 IB: B 0 IC: ?

Couldn't this be solved with offset?
IC > IA=0,IB=+IA

and how does the object do that?

TC=class(IA,IB,IC)

or if I understand it correctly object has this solved in vmt, and interface posseses no internal vmt

Still no idea what so ever. What can you do ?

Nevermind, didn't expect that anyway

Do that everyday, never missed foreach.
you != me != people;
Nevermind();
Show quoted text 10 lines
So in short you say you use iterators on one spot. Mmany languages have iterator systems, but most don't have the silly syntactic sugar foreach. So in your case it is only short for x:=startiter; while x,iterateover do y;

yes. did you expect anything else? most best solutions are simple

Show quoted text 16 lines
So again it is actually only a shorthand notation for something that can be done perfectly otherwise. (Write them out, and test all interfaces) One can think up a terse short notation for _every_ construct there is, that _somebody_ uses a lot, but it will only blow up language and runtime, and eat up developer time. To give you an counter example: Personally the only thing currently on my wishlist are generics. But that is a bit too hefty to implement shortterm. Why generics? They really allow things that can't be done: - typesafe containers. - parameterising algoratims with types in general.

generics in pascal?
you lost me there. Generics are nothing but typesafe declarations, used in higher languages like c# and java.. In c# every variable, record or class is descedant of object. And generics are nothing but speedup for untyped access aka. boxing/unboxing of variables
where boxing is nothing else but
object a = string s;
But since this one comes with performance cost generics were declared in c#
class <int> List

pascal does not suffer from box/unbox timing
in fact pascal does not support box/unbox

But probably you know what you talk about, I'm not going to bother for explanation

Show quoted text 6 lines
It is also significantly more heavy weight. That is not necessarily bad, it is just what you choose for. Delphi has enough room to implement frameworks on top of it. And not only for this solution. Moreover one can take over the designer via the toolsapi without access to delphi.

I was pointing out how bad default windows interface is

Show quoted text 5 lines
It will be interesting to see your patches then. Maybe I'll change my opinion if I have played with your fork of the code.

Fork? if there would be patches they would be insignificant, but since I'm inside of tech preview for my project this would mean that fpc would go out of race for this project before I would started patching either solution is simple and supported directly or not

_______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

---------------------------------------------------------------------- This mail sent through Horde-Toaster (http://qmailtoaster.clikka.com/)

Reply by email

Nikolai Zhubr
to Unknown author

Hi,
Monday, 21 March, 2005, 8:58:07, ml at brainwashers dot org wrote: [...]

Fork? if there would be patches they would be insignificant, but since I'm inside of tech preview for my project this would mean that fpc would go out of race for this project before I would started patching either solution is simple and supported directly or not

Like with commercial software in some sense,
support you get = contribution you make, well except for some trivial help and explanations not really requiring developers to spend their days and weeks working personally for you for free. Contribution is typically accepted in form of patches and/or bugreports, not money though.
AFAIK and IMHO, free pascal project is not really in any race with delphi or whatever else. No-one ever claimed this here IIRC. Note: I'm not a developer of FPC.

Best regards, Nikolai Zhubr

Reply by email

Marco van de Voort
to Unknown author: Quoting Marco van de Voort : Could you explain this extra a little more? Hope its not…
Show quoted text 14 lines
Quoting Marco van de Voort : > > Afaik not, you have a pointer to an interface table, And even if you can get > to the object vmt from there, you don't know anything about it. interface is > all about information hiding. It might not even be a proper Pascal object. > > No, the whole idea of property is simply to easily declare iDE editable > values. As nice added extra: the ability to change from direct field to > getter/setter based access easily. (read: without changes in the calling > code) > Could you explain this extra a little more?

RTTI (introspection in Java lingo) is generated for properties. This is used by the IDE/Rad, but the whole principles are general.

Show quoted text 8 lines
> Nonsense. Python and perl etc were launched in the bubble era and are still > floating on that capital. However there is a lot of hype and tinkering,and > little real work done in it. Of course, enough hype will ensure that some > stuff will be done, but I don't really have the feeling that the hype and > actual serious use are in any sane proportion. > Little work? Guess we live in different world

Yup.

Show quoted text 8 lines
> > IB: > B 0 > > IC: ? Couldn't this be solved with offset? IC > IA=0,IB=+IA

No. Keep in mind that I can assign IC to a variable of both IA and IB. And those specify their first this case setting IB's 1 st method to 4 would solve some stuff, but that is not a generic solution.

In general this _is_ the multiple inheritance problem, together with initialisation order and what you do if you have methods with the same name.

Interfaces is simply a basic form of MI modeled to avoid the worst pitfalls, and now you are trying to bring it back via the backdoor.

and how does the object do that?

A table for each interface I guess. And, more important, there are no relations to keep between the interfaces IA,IB,IC in below example.

TC=class(IA,IB,IC) or if I understand it correctly object has this solved in vmt, and interface posseses no internal vmt

There parts of the per object tables that deal with interfaces. I assume an interface reference is a reference to this?

Show quoted text 12 lines
> > To give you an counter example: Personally the only thing currently on my > wishlist are generics. But that is a bit too hefty to implement shortterm. > > Why generics? They really allow things that can't be done: > - typesafe containers. > - parameterising algoratims with types in general. > generics in pascal? you lost me there. Generics are nothing but typesafe declarations, used in higher languages like c# and java.

This is not true. C# and Java only got them in their last iteration. Ada and C++ are much older implementations, and they don't have the stuff below.

pascal does not suffer from box/unbox timing in fact pascal does not support box/unbox

No. It can be used for this (it is part of the typesafe container stuff), but one can also parameterise code.

The token example is a generic sorting routine. E.g. the bubble sort:

procedure bubblesort<T>(a:array of T);  // T is the type
var  tmp : T;
begin
for i:=0 to n-1 do
  for j:=0 to n-1-i do
   begin
    if array[j+1] < a[j] then
      begin
        tmp:=a[j]; a[j]:=a[j+1];
        a[j+1]:=tmp;
      end;
   end;
end;

The trick is that above code is general, except for the type, since array access, the compare, and the swapping depend on the type.

Generics allow this kind of code to be parameterised by the type and instantiate the code per type.

Reasons can be:
- typesafety (which can also save you autoboxing)
- speed (typical example above works with compare/swap as procedure vars with call overhead and bad optimisation)
- reuse of code in general.

Show quoted text 6 lines
> It is also significantly more heavy weight. That is not necessarily bad, > it is just what you choose for. Delphi has enough room to implement > frameworks on top of it. And not only for this solution. Moreover one > can take over the designer via the toolsapi without access to delphi. I was pointing out how bad default windows interface is

It has flaws, certainly. However I have not seen something that has no downsides. A lot of interfaces that try to do it all are unbearably slow.

I e.g. checked out OS X's COCOA a while back, and all the Objective C runtime interfacing also doesn't really feel "easy".

Show quoted text 8 lines
> It will be interesting to see your patches then. Maybe I'll change my > opinion > if I have played with your fork of the code. Fork? if there would be patches they would be insignificant, but since I'm inside of tech preview for my project this would mean that fpc would go out of race for this project before I would started patching either solution is simple and supported directly or not

Well, I doubt developers will abandon their schedules to implement features like this.

Reply by email

Jonas Maebe
to Marco van de Voort: Afaik not, you have a pointer to an interface table, And even if you can get to the…
Marco van de Voort wrote 5 lines
Nonsense. Python and perl etc were launched in the bubble era and are still floating on that capital. However there is a lot of hype and tinkering,and little real work done in it.

If this kind of silly discussions have to be held, please do so on fpc-other (I'm not talking about the rest of the mail).

Jonas
FPC mailing list admin

Reply by email

ml
to Marco van de Voort: RTTI (introspection in Java lingo) is generated for properties. This is used by the…
> Quoting Marco van de Voort :

Like first, I wouldn't like to spam this mailing list about interfaces. Can I contact you directly or somewhere else?

I would like to try to patch some things but I would probably have few questions how to implement it to satisfy everybody, or the general interfaces idea and implementation.

One major problem with interfaces is class <=> interface <=> class inflexibility and this is the root of everything.

imagine interfaces declared IA, IB, IC, ID, and all standalone
TA=class(TInterfacedObject,IA,IB,IC);
var
  a: IA; b: IB; c: IC; d: ID; obj: TA;
begin
  a := obj; // result is pointer(obj) + 12;
  b := obj; // result is pointer(obj) + 16;
  c := obj; // result is pointer(obj) + 20;
// Following is nonsense, its just like "as" would be direct
// call to exception if you try to use class that inherits more
// than one interface
  a := (object as IA); // correct
  b := (object as IB); // returns pointer to the first interface vmt=IA
  c := (object as IC); // returns pointer to the first interface vmt=IA
// there's no way to do again it's like direct call to exception
  obj := a; // returns pointer(obj) + 12 ???
// because of the previous offset problems calling both next
// things is impossible (or better to say it is always false),
// this is true only when IB would be inherited from IA
  if Supports(b, IA) then
    IA(b).something;
  if Supports(b, IA) then
    a := b;
end;

I have a working idea how to solve this problem (without loosing any compatibility or any drastic change, in fact changing very little) but I would like to hear your opinion on my proposal first. Change is fairly simple, and after my change everything here becomes possible and safer. And since every problem I named here produces either compiler error or exception now already, there would be no difference if somebody would use it incorrectly.

  a := d; // produce exception when assigning

or used correctly, which leads to much safer interface code, where runtime is much more flexible

  if Supports(a, ID) then
    a := d;
Marco van de Voort wrote 84 lines
> > > > > Afaik not, you have a pointer to an interface table, And even if you can get > > to the object vmt from there, you don't know anything about it. interface is > > all about information hiding. It might not even be a proper Pascal object. > > > > No, the whole idea of property is simply to easily declare iDE editable > > values. As nice added extra: the ability to change from direct field to > > getter/setter based access easily. (read: without changes in the calling > > code) > > > > Could you explain this extra a little more? RTTI (introspection in Java lingo) is generated for properties. This is used by the IDE/Rad, but the whole principles are general. > > Nonsense. Python and perl etc were launched in the bubble era and are still > > floating on that capital. However there is a lot of hype and tinkering,and > > little real work done in it. Of course, enough hype will ensure that some > > stuff will be done, but I don't really have the feeling that the hype and > > actual serious use are in any sane proportion. > > > > Little work? Guess we live in different world Yup. > > > > IB: > > B 0 > > > > IC: ? > > Couldn't this be solved with offset? > IC > IA=0,IB=+IA No. Keep in mind that I can assign IC to a variable of both IA and IB. And those specify their first method at 0. In this case setting IB's 1 st method to 4 would solve some stuff, but that is not a generic solution. In general this _is_ the multiple inheritance problem, together with initialisation order and what you do if you have methods with the same name. Interfaces is simply a basic form of MI modeled to avoid the worst pitfalls, and now you are trying to bring it back via the backdoor. > and how does the object do that? A table for each interface I guess. And, more important, there are no relations to keep between the interfaces IA,IB,IC in below example. > TC=class(IA,IB,IC) > or if I understand it correctly object has this solved in vmt, and interface > posseses no internal vmt There parts of the per object tables that deal with interfaces. I assume an interface reference is a reference to this? > > > > To give you an counter example: Personally the only thing currently on my > > wishlist are generics. But that is a bit too hefty to implement shortterm. > > > > Why generics? They really allow things that can't be done: > > - typesafe containers. > > - parameterising algoratims with types in general. > > > > generics in pascal? > you lost me there. Generics are nothing but typesafe declarations, used in > higher languages like c# and java. This is not true. C# and Java only got them in their last iteration. Ada and C++ are much older implementations, and they don't have the stuff below. > pascal does not suffer from box/unbox timing > in fact pascal does not support box/unbox No. It can be used for this (it is part of the typesafe container stuff), but one can also parameterise code.

this is nice. boxing/unboxing and then typed unboxing :D

Show quoted text 21 lines
The token example is a generic sorting routine. E.g. the bubble sort: procedure bubblesort<T>(a:array of T); // T is the type var tmp : T; begin for i:=0 to n-1 do for j:=0 to n-1-i do begin if array[j+1] < a[j] then begin tmp:=a[j]; a[j]:=a[j+1]; a[j+1]:=tmp; end; end; end; The trick is that above code is general, except for the type, since array access, the compare, and the swapping depend on the type.

in c# this is solved trough operators, one has to define them for a new type. And I like it

Show quoted text 34 lines
Generics allow this kind of code to be parameterised by the type and instantiate the code per type. Reasons can be: - typesafety (which can also save you autoboxing) - speed (typical example above works with compare/swap as procedure vars with call overhead and bad optimisation) - reuse of code in general. > > It is also significantly more heavy weight. That is not necessarily bad, > > it is just what you choose for. Delphi has enough room to implement > > frameworks on top of it. And not only for this solution. Moreover one > > can take over the designer via the toolsapi without access to delphi. > > I was pointing out how bad default windows interface is It has flaws, certainly. However I have not seen something that has no downsides. A lot of interfaces that try to do it all are unbearably slow. I e.g. checked out OS X's COCOA a while back, and all the Objective C runtime interfacing also doesn't really feel "easy". > > It will be interesting to see your patches then. Maybe I'll change my > > opinion > > if I have played with your fork of the code. > Fork? if there would be patches they would be insignificant, but since I'm > inside of tech preview for my project this would mean that fpc would go > out of race for this project before I would started patching either > solution is simple and supported directly or not Well, I doubt developers will abandon their schedules to implement features like this.

Never asked for that (I'm more like do it alone and don't whine type), maybe I said it a bit strange (English is not my native language). If simple patches are possible, then I would like to try that, but forking already working solution just because of me, would be unfair and too hard for me alone. If forking would be the answer, then I would probably choose other language.

_______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Michael Van Canneyt
to ml
ml wrote 12 lines
>> Quoting Marco van de Voort : Like first, I wouldn't like to spam this mailing list about interfaces. Can I contact you directly or somewhere else? I would like to try to patch some things but I would probably have few questions how to implement it to satisfy everybody, or the general interfaces idea and implementation. One major problem with interfaces is class <=> interface <=> class inflexibility and this is the root of everything.

Classes are fundamentally different from Interfaces. Interfaces only specify a set of methods (a VMT, essentially) where classes also contain data. When a class implements an interface, it just means that all methods as specified in the interface are available.

Show quoted text 18 lines
imagine interfaces declared IA, IB, IC, ID, and all standalone TA=class(TInterfacedObject,IA,IB,IC); var a: IA; b: IB; c: IC; d: ID; obj: TA; begin a := obj; // result is pointer(obj) + 12; b := obj; // result is pointer(obj) + 16; c := obj; // result is pointer(obj) + 20; // Following is nonsense, its just like "as" would be direct // call to exception if you try to use class that inherits more // than one interface a := (object as IA); // correct b := (object as IB); // returns pointer to the first interface vmt=IA c := (object as IC); // returns pointer to the first interface vmt=IA // there's no way to do again it's like direct call to exception obj := a; // returns pointer(obj) + 12 ???

This is nonsense. You cannot assign an interface to a class. A class IMPLEMENTS an interface, it is not an interface.

Michael.

Reply by email

Marco van de Voort
to Michael Van Canneyt
Show quoted text 10 lines
On Tue, 22 Mar 2005, ml wrote: > // than one interface > a := (object as IA); // correct > b := (object as IB); // returns pointer to the first interface vmt=IA > c := (object as IC); // returns pointer to the first interface vmt=IA > // there's no way to do again it's like direct call to exception > obj := a; // returns pointer(obj) + 12 ??? This is nonsense. You cannot assign an interface to a class. A class IMPLEMENTS an interface, it is not an interface.

Ml, see my original message. If you have an interface, you know nothing of the stuff the class adds outside that interface.

Assigning/converting an interface to a class is impossible, which can be shown by this example.

Var intf : IA;           // has method C
    cl   : SomeClass;    // has method A,B
begin
  intf:=someclass.create;  // get reference to list with methods of interface
  cl:=intf;		   // assign list with methods of interface to
			   // list of methods of class.
  cl.a;			   // cl has no knowledge about anything .c this
			   // can't work.
end;

Even though at the point of "someclass.create" all info about the class is available, only a list of offsets for methods in the interface is passed. (so only method C at offset 0 in that table)

When assigning intf to cl, you assign that table back to the cl, the full which needs a full VMT, with info about A and B. This makes the third statement (cl.a) impossible.

Reply by email

Unknown author
to Marco van de Voort

Quoting Marco van de Voort :

> On Tue, 22 Mar 2005, ml wrote: > > // than one interface > > a := (object as IA); // correct > > b := (object as IB); // returns pointer to the first interface

vmt=IA

> > c := (object as IC); // returns pointer to the first interface

vmt=IA

Show quoted text 5 lines
> > // there's no way to do again it's like direct call to exception > > obj := a; // returns pointer(obj) + 12 ??? > > This is nonsense. You cannot assign an interface to a class. > A class IMPLEMENTS an interface, it is not an interface.

Ok, its nonsense. I said it already works with my patch, but I guess you know it better. So my example down there doesn't work (with patch). You should know.
I (; can't ;) transfer from one interface to other back to object and to 3rd interface. I just imagine my results.

Ml, see my original message. If you have an interface, you know

nothing of

the stuff the class adds outside that interface.

Wrong. 10 minutes (looking trough sources, seeing where the problem is and implementing my patch) and everything worked.

Getting Me: TObject enables you to call all class functions. So you can compare class compatibility or anything (directly from interface).

My implementation works ok, I was just worried a little about implementation (I wouldn't want to break any COM interface, I'm not a windows person and I just wanted to ask for wished approach on as and operators and one more or less cosmetic approach, as I said I'm not using windows and I wouldn't want to break anything). In Linux this patch breaks nothing and adds 0 changes to previous sources that used interfaces. The only added function Me is already solved and that's all.

But my best guess is that you're not interested in patch, anyway here it is. All it needs now are "as" and := operators implemented correctly. I plan to do that too, just as multiple interface inheritance (yes, it is possible, the only problem is looking at the problem from the right side. As long as you look at this thing as you described it, it is a no go. If you turn around and open your eyes solution is as simple as possible, the only problem is that you don't look at interface as you should). If I plan correctly by the end of the weekend (it would be even less if I would get some usable answers instead of "this doesn't work") everything should work (I selected fpc (it has all I need, as I said I don't mind little patches) for this job I'll be working on).

Show quoted text 16 lines
Assigning/converting an interface to a class is impossible, which can be shown by this example. Var intf : IA; // has method C cl : SomeClass; // has method A,B begin intf:=someclass.create; // get reference to list with methods of interface cl:=intf; // assign list with methods of interface to // list of methods of class. cl.a; // cl has no knowledge about anything .c this // can't work. end; Even though at the point of "someclass.create" all info about the

class is

available, only a list of offsets for methods in the interface is

passed.

(so only method C at offset 0 in that table)

Yeah, heard that already, and the reason for that is that you don't provide what is needed

When assigning intf to cl, you assign that table back to the cl, the

full

Show quoted text 9 lines
which needs a full VMT, with info about A and B. This makes the third statement (cl.a) impossible. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

And the test source.

program project4;
{$mode objfpc}{$H+}{$MACRO+}

uses
Classes, SysUtils, libc

  { add your units here };
type
  IA = interface
    procedure A;
    function Me: TInterfacedObject;
  end;
  IB = interface
    procedure B;
  end;
  IC = interface(IA)
    procedure C;
  end;
  ID = interface
    procedure D;
  end;
  TD = class(TInterfacedObject)
  end;
  TC = class(TD, IA, IB, IC, ID)
    constructor Create;
    destructor Destroy; override;
//    function Me: TInterfacedObject;
    procedure A;
    procedure B;
    procedure C;
    procedure D;
  end;
  constructor TC.Create;
  begin
    inherited Create;
    A;
    B;
    C;
  end;
  destructor TC.Destroy;
  begin
    Writeln('TC.Destroy');
    inherited Destroy;
  end;
  procedure TC.A;
  begin
    Writeln('a');
  end;
  procedure TC.B;
  begin
    Writeln('b');
  end;
  procedure TC.C;
  begin
    Writeln('c');
  end;
  procedure TC.D;
  begin
    Writeln('ddddddddddddddd');
  end;
function Equals(const source: IUnknown): TObject;
begin
  Result := source.Me;
end;
function SupportsInterface(aInterface: IUnknown; aIID: TGUID): boolean;
begin
  Result := Supports(aInterface, aIID);
end;
function SupportsInterface(aClass: TClass; aIID: TGUID): boolean;
begin
  Result := false;
  if (aClass  nil) then
    if aClass.InheritsFrom(TInterfacedObject) then
      Result := SupportsInterface(IUnknown(aClass), aIID);
end;
procedure testD(obj: ID);
begin
  writeln('inside testD');
  if obj  nil then
    obj.D
  else
    writeln('ua');
  if SupportsInterface(obj, ID) then
    writeln('yes')
  else
    writeln('ua');
end;
var
  c: char;
  AAAA: integer;
  t: TC;
  a: IA;
  b: IB;
  d: ID;
  t2: TC;
  cf: IUnknown;
  cc: IC;
  k: TInterfacedObject;
begin
  Writeln(SizeOf(cf));
  t := TC.Create;
  a := t;
  b := t;
  AAAA := 500;
  d := t;
  cc := t;
  a.A;
  b.B;
  writeln('t: ', integer(pointer(t)), ' --- a: ', integer(pointer(a)), '
--- b: ', integer(pointer(b)), ' --- d: ', integer(pointer(d)));
  // here as should be treated same as :=
  writeln('t: ', integer(pointer(t)), ' --- a: ', integer(pointer(t as
IA)), ' --- b: ', integer(pointer(t as IB)), ' --- d: ', integer(pointer
(t as ID)));
  t2 := TC(Equals(a));
  writeln('t2: ', integer(pointer(t2)));
  t2 := TC(Equals(cc));
  writeln('t2: ', integer(pointer(t2)));
  d := nil;
  d := t2; // if you look here I derived ID from IC, which is not
possible as you say
  d.d;
  a.A;
  b.B;
  // some junk testing code
  if (t.InheritsFrom(TD)) then
    Writeln('Inherits from TD')
  else
    Writeln('Does not Inherits from TD');
  try
    if SupportsInterface(t, IB) then
      if SupportsInterface(cc, IA) then
        if SupportsInterface(d, IB) then
          writeln('yes')
        else
          writeln('nope');
  except
    writeln('nope, error');
  end;
  writeln('testD');
  testD(ID(t));
  a := nil;
  b := nil;
  cc := nil;
  d := nil;
end.

---------------------------------------------------------------------- This mail sent through Horde-Toaster (http://qmailtoaster.clikka.com/)

Reply by email

Michael Van Canneyt
to Unknown author
Show quoted text 20 lines
Quoting Marco van de Voort : >> On Tue, 22 Mar 2005, ml wrote: >>> // than one interface >>> a := (object as IA); // correct >>> b := (object as IB); // returns pointer to the first interface vmt=IA >>> c := (object as IC); // returns pointer to the first interface vmt=IA >>> // there's no way to do again it's like direct call to exception >>> obj := a; // returns pointer(obj) + 12 ??? >> >> This is nonsense. You cannot assign an interface to a class. >> A class IMPLEMENTS an interface, it is not an interface. Ok, its nonsense. I said it already works with my patch, but I guess you know it better. So my example down there doesn't work (with patch). You should know. I (; can't ;) transfer from one interface to other back to object and to 3rd interface. I just imagine my results.

Tell me, what is

   obj := a;

supposed to DO ? A class has a set of methods. Some of these methods form the VMT of an interface. What your code does, is say "don't use your VMT methods, use these instead' ?

Michael.

Reply by email

Unknown author
to Michael Van Canneyt

Quoting Michael Van Canneyt :

Show quoted text 32 lines
On Wed, 23 Mar 2005 wrote: > Quoting Marco van de Voort : > >>> On Tue, 22 Mar 2005, ml wrote: >>>> // than one interface >>>> a := (object as IA); // correct >>>> b := (object as IB); // returns pointer to the first interface > vmt=IA >>>> c := (object as IC); // returns pointer to the first interface > vmt=IA >>>> // there's no way to do again it's like direct call to exception >>>> obj := a; // returns pointer(obj) + 12 ??? >>> >>> This is nonsense. You cannot assign an interface to a class. >>> A class IMPLEMENTS an interface, it is not an interface. > > Ok, its nonsense. I said it already works with my patch, but I guess you > know it better. So my example down there doesn't work (with patch). You > should know. > I (; can't ;) transfer from one interface to other back to object and to > 3rd interface. I just imagine my results. Tell me, what is obj := a; supposed to DO ? A class has a set of methods. Some of these methods form the VMT of an interface. What your code does, is say "don't use your VMT methods, use these instead' ?

Yes, exactly. I even provided test example at the bottom of my previous message, where I transfered from class to IA, back to class and then to ID. And called ID.D; And it just works (this is also nice start for blind properties implementation, which now also became possible, since original vmt is now visible)

But, It should be used as

if (TObject(a).InheritedFrom(TSomeClass)) then begin
  obj := TSomeClass(a); // note that here obj is declared as TSomeClass
  // now safely use as this vmt
end;
if SupportsInterface(TObject(a), IB) then begin
  ibvar := a;  // declared ibvar: IB
  // now safely use as this vmt
end;

in perfect world "is" would return InheritedFrom or SupportsInterface result and not actual class check, if true then all needed operations are satisfied.

Now how it could be:
if (a is TSomeClass) then // if "is" and "as" would be perfectly handled

  obj := (a as TSomeClass);

if (a is IB) then // if "is" and "as" would be perfectly handled

  ibvar := (a as IB);

Now if someone could say that this isn't beautifull or readable

safetype checking MUST BE USED for Interface to (Interface or class) vmt translation, as I specified above

p.s. At the bottom of the message I provided complete program for testing and you ask me about the one I provided to show problems with current interfaces as they are in fpc 1.9.8 (that was few messages ago)????

In virtual (virtual just as in trying to use as different type than one that was passed) interface usage additional safety code is needed. And it is not even a bit different than checking if pointer or class is nil before using it. As I already said, pascal interfaces in current state are NOT usable, even := and "as" are not treated consistantly (they should be otherwise "as" is rendered as unusable because it almost always invokes exception *bad vmt is passed when more than one interface is inherited in class). I have a few imeplementation

Virtual type access has its cost in speed but flexibility is a major boost. Have an working implementation idea for multiple interface inheritance too, and that one will just work too (ok, as soon as I find all the parts of code that need patching, but solution patch (and I mean complete solution not hacked one) probably won't be more than 40 lines long).

After all patches (vmt patch, blind properties, as and is, multiple inheritance), interfaces could become as powerfull and beatifull as interfaces should be. I think that cost of all patches will be about 100-150 lines long

ml

Show quoted text 7 lines
Michael. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

---------------------------------------------------------------------- This mail sent through Horde-Toaster (http://qmailtoaster.clikka.com/)

Reply by email

Michael Van Canneyt
to Unknown author
Show quoted text 54 lines
Quoting Michael Van Canneyt : > > > On Wed, 23 Mar 2005 wrote: > >> Quoting Marco van de Voort : >> >>>> On Tue, 22 Mar 2005, ml wrote: >>>>> // than one interface >>>>> a := (object as IA); // correct >>>>> b := (object as IB); // returns pointer to the first interface >> vmt=IA >>>>> c := (object as IC); // returns pointer to the first interface >> vmt=IA >>>>> // there's no way to do again it's like direct call to exception >>>>> obj := a; // returns pointer(obj) + 12 ??? >>>> >>>> This is nonsense. You cannot assign an interface to a class. >>>> A class IMPLEMENTS an interface, it is not an interface. >> >> Ok, its nonsense. I said it already works with my patch, but I guess you >> know it better. So my example down there doesn't work (with patch). You >> should know. >> I (; can't ;) transfer from one interface to other back to object and to >> 3rd interface. I just imagine my results. > > Tell me, what is > > obj := a; > > supposed to DO ? A class has a set of methods. Some of these methods form > the VMT of an interface. What your code does, is say > "don't use your VMT methods, use these instead' ? Yes, exactly. I even provided test example at the bottom of my previous message, where I transfered from class to IA, back to class and then to ID. And called ID.D; And it just works (this is also nice start for blind properties implementation, which now also became possible, since original vmt is now visible) But, It should be used as if (TObject(a).InheritedFrom(TSomeClass)) then begin obj := TSomeClass(a); // note that here obj is declared as TSomeClass // now safely use as this vmt end; if SupportsInterface(TObject(a), IB) then begin ibvar := a; // declared ibvar: IB // now safely use as this vmt end; in perfect world "is" would return InheritedFrom or SupportsInterface result and not actual class check, if true then all needed operations are satisfied.

I can understand that 'is' should be able to check interfaces; this is a useful patch.

I also understand what your code should do.

BUT I see some flaws in your design.

  IA = Interface
    procedure InitF;
  end;
  TA = class(TObject,IA)
    F : TList;
    Procedure InitF;
    Procedure B;
  end;
  Procedure TA.InitF;
  begin
    F:=Tlist.Create;
  end;
  Procedure TA.B;
  begin
    F.Add(SomePointer);
  end;
Var
   A : TA;
   C : IA;
begin
   A:=TA.Create;
   C:=SomeIA;    // Get an IA interface from somewhere.
   A:=C;
   A.InitF;      // <<--- Which InitF should be used ?
   A.B;          // Crash or not ?
end;
If TA.InitF is used, then B runs OK, but then A:=C has no  the InitF from C is used, then F will not be initialized, and B will
fail.

Michael.

Reply by email

ml
to Michael Van Canneyt
Michael Van Canneyt wrote 94 lines
On Thu, 24 Mar 2005 wrote: > Quoting Michael Van Canneyt : > >> >> >> On Wed, 23 Mar 2005 wrote: >> >>> Quoting Marco van de Voort : >>> >>>>> On Tue, 22 Mar 2005, ml wrote: >>>>>> // than one interface >>>>>> a := (object as IA); // correct >>>>>> b := (object as IB); // returns pointer to the first interface >>> vmt=IA >>>>>> c := (object as IC); // returns pointer to the first interface >>> vmt=IA >>>>>> // there's no way to do again it's like direct call to exception >>>>>> obj := a; // returns pointer(obj) + 12 ??? >>>>> >>>>> This is nonsense. You cannot assign an interface to a class. >>>>> A class IMPLEMENTS an interface, it is not an interface. >>> >>> Ok, its nonsense. I said it already works with my patch, but I guess you >>> know it better. So my example down there doesn't work (with patch). You >>> should know. >>> I (; can't ;) transfer from one interface to other back to object and to >>> 3rd interface. I just imagine my results. >> >> Tell me, what is >> >> obj := a; >> >> supposed to DO ? A class has a set of methods. Some of these methods form >> the VMT of an interface. What your code does, is say >> "don't use your VMT methods, use these instead' ? > > Yes, exactly. I even provided test example at the bottom of my previous message, > where I transfered from class to IA, back to class and then to ID. And called > ID.D; And it just works (this is also nice start for blind properties > implementation, which now also became possible, since original vmt is now visible) > > But, It should be used as > > if (TObject(a).InheritedFrom(TSomeClass)) then begin > obj := TSomeClass(a); // note that here obj is declared as TSomeClass > // now safely use as this vmt > end; > > if SupportsInterface(TObject(a), IB) then begin > ibvar := a; // declared ibvar: IB > // now safely use as this vmt > end; > > in perfect world "is" would return InheritedFrom or SupportsInterface result and > not actual class check, if true then all needed operations are satisfied. I can understand that 'is' should be able to check interfaces; this is a useful patch. I also understand what your code should do. BUT I see some flaws in your design. IA = Interface procedure InitF; end; TA = class(TObject,IA) F : TList; Procedure InitF; Procedure B; end; Procedure TA.InitF; begin F:=Tlist.Create; end; Procedure TA.B; begin F.Add(SomePointer); end; Var A : TA; C : IA; begin

Completely wrong type of thinking here, and I can't answer you what you asked, so I provided answer why I can't answer and how it should be used

A:=TA.Create; C:=SomeIA; // Get an IA interface from somewhere.

Why would someone create one object just to override its variable with some other value? To create memory leaks?

A:=C; A.InitF; // <<--- Which InitF should be used ? A.B; // Crash or not ?

:? Depends, but your example is one complete mistake of using this. It makes sense just as my example with pointer down here. So... would it crash? Yeah, probably just the same as

var
  p, r: pchar;
  i: integer;
begin
  GetMem(p, 100);
  for i := 0 to 10000000 do
    p[i] := #0;
  GetMem(r, 1000);
  p := r; // I intentionally haven't freed pointer
          // like you didn't in your example
  // So, how does pascal handle this? It can't.
  // Those who code should know what they do
end;

Question here is different. Was that my mistake as programmer or fpc mistake for not predicting my stupidity. Guess what, it wasn't fpc fault, so if some interfaced object doesn't initialize its variables, and others do. Correct the problem there and don't blame wrong implementation.

end;

If you would at least write

  Procedure TA.B;
begin
      if F = nil then
        F:=TList.Create;
F.Add(SomePointer); end;

your example would work

If TA.InitF is used, then B runs OK, but then A:=C has no meaning at all. If the InitF from C is used, then F will not be initialized, and B will fail.

Here we go again. Your main problem is that you don't understand (or you lack imagination) what interface is in his complete feature set. Main feature of interfaces is to have ability to predict combinations of commands that interfaces support, as I already specified... having monolithic interface structure makes no sense (you just get mirror copy of classes), it's a waste of time, paper and space. And before you answer how it is not possible, or how you don't have time to implement it. I'm game. I'm prepared to make all the necessary changes and patches. All that I would ask for is a few pointers (if that could be done on line on some irc or msn channel, that would be perfect, it's hard to talk in one e-mail a day) how and where so that I don't need to dissect complete compiler code (you probably understand that I'm not as familiar with its code as you are, that would be only few questions like "where does it...", "how does it...", "what would be the preffered implementation of ...").

Here is a simple example how it should be used

type
  IReportable = interface
    function Report: string;
    // let's say that this should write report and
    // return status description as string
  end;
  ILogged = interface
    procedure Log(aStr: string);
  end;

And now some completely different place in your software, main feature of interfaces is that you can predict possible features, and not even start to implement them at that moment

procedure MyXYZPart.DoReport(aRep: IReportable);
begin
  if (aRep  nil) then begin
    if (aRep is ILogged) then
      (aRep as ILogged).Log(aRep.Report)
    else
      aRep.Report
end;

Meaning, that if I derived some class as (and call DoReport with it as parameter)
type
TSomeClass = interface(TInterfacedObject, IReportable, ILogged)

this class will have to contain all the logging facility needed, and that's conditioned with interfaces (otherwise it won't be compiled).

TSomeClass2 = interface(TInterfacedObject, IReportable)

this class will automatically skip logging, because logging interface is not supported by class

What is difference here? I could pass a simple interfaced object as parameter and predict possibility of logging. If object or interface support that option then all the facility needed is supported and logging is done.

This is how and why interfaces should be used, for predicting features. And with interfaces as they are this is just impossible.

I hope that you start seeing power behind more flexible interfaces

ml

Show quoted text 5 lines
Michael. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Michael Van Canneyt
to ml
ml wrote 104 lines
On Thu, 2005-03-24 at 09:06 +0100, Michael Van Canneyt wrote: > > On Thu, 24 Mar 2005 wrote: > >> Quoting Michael Van Canneyt : >> >>> >>> >>> On Wed, 23 Mar 2005 wrote: >>> >>>> Quoting Marco van de Voort : >>>> >>>>>> On Tue, 22 Mar 2005, ml wrote: >>>>>>> // than one interface >>>>>>> a := (object as IA); // correct >>>>>>> b := (object as IB); // returns pointer to the first interface >>>> vmt=IA >>>>>>> c := (object as IC); // returns pointer to the first interface >>>> vmt=IA >>>>>>> // there's no way to do again it's like direct call to exception >>>>>>> obj := a; // returns pointer(obj) + 12 ??? >>>>>> >>>>>> This is nonsense. You cannot assign an interface to a class. >>>>>> A class IMPLEMENTS an interface, it is not an interface. >>>> >>>> Ok, its nonsense. I said it already works with my patch, but I guess you >>>> know it better. So my example down there doesn't work (with patch). You >>>> should know. >>>> I (; can't ;) transfer from one interface to other back to object and to >>>> 3rd interface. I just imagine my results. >>> >>> Tell me, what is >>> >>> obj := a; >>> >>> supposed to DO ? A class has a set of methods. Some of these methods form >>> the VMT of an interface. What your code does, is say >>> "don't use your VMT methods, use these instead' ? >> >> Yes, exactly. I even provided test example at the bottom of my previous message, >> where I transfered from class to IA, back to class and then to ID. And called >> ID.D; And it just works (this is also nice start for blind properties >> implementation, which now also became possible, since original vmt is now visible) >> >> But, It should be used as >> >> if (TObject(a).InheritedFrom(TSomeClass)) then begin >> obj := TSomeClass(a); // note that here obj is declared as TSomeClass >> // now safely use as this vmt >> end; >> >> if SupportsInterface(TObject(a), IB) then begin >> ibvar := a; // declared ibvar: IB >> // now safely use as this vmt >> end; >> >> in perfect world "is" would return InheritedFrom or SupportsInterface result and >> not actual class check, if true then all needed operations are satisfied. > > I can understand that 'is' should be able to check interfaces; this is a > useful patch. > > I also understand what your code should do. > > BUT I see some flaws in your design. > > IA = Interface > procedure InitF; > end; > > > TA = class(TObject,IA) > F : TList; > Procedure InitF; > Procedure B; > end; > > Procedure TA.InitF; > > begin > F:=Tlist.Create; > end; > > Procedure TA.B; > > begin > F.Add(SomePointer); > end; > > > Var > A : TA; > C : IA; > > begin Completely wrong type of thinking here, and I can't answer you what you asked, so I provided answer why I can't answer and how it should be used > A:=TA.Create; > C:=SomeIA; // Get an IA interface from somewhere. Why would someone create one object just to override its variable with some other value? To create memory leaks?

Hey, the

     A:=C;

was supposed to be the equivalent of YOUR code :

   // there's no way to do again it's like direct call to exception
   obj := a; // returns pointer(obj) + 12 ???

?

[...]

Show quoted text 8 lines
Here we go again. Your main problem is that you don't understand (or you lack imagination) what interface is in his complete feature set. Main feature of interfaces is to have ability to predict combinations of commands that interfaces support, as I already specified... having monolithic interface structure makes no sense (you just get mirror copy of classes), it's a waste of time, paper and space. And before you answer how it is not possible, or how you don't have time to implement it.

I was not going to answer any of this, I'm trying to understand what you want to accomplish, and why this could be useful for other people.

Show quoted text 34 lines
I'm game. I'm prepared to make all the necessary changes and patches. All that I would ask for is a few pointers (if that could be done on line on some irc or msn channel, that would be perfect, it's hard to talk in one e-mail a day) how and where so that I don't need to dissect complete compiler code (you probably understand that I'm not as familiar with its code as you are, that would be only few questions like "where does it...", "how does it...", "what would be the preffered implementation of ..."). Here is a simple example how it should be used type IReportable = interface function Report: string; // let's say that this should write report and // return status description as string end; ILogged = interface procedure Log(aStr: string); end; And now some completely different place in your software, main feature of interfaces is that you can predict possible features, and not even start to implement them at that moment procedure MyXYZPart.DoReport(aRep: IReportable); begin if (aRep nil) then begin if (aRep is ILogged) then (aRep as ILogged).Log(aRep.Report) else aRep.Report end;

I see what you want, but if you would do

procedure MyXYZPart.DoReport(aRep: TInterfacedObject);
begin
   if (aRep  nil) and arep is IReportable then begin
     if (aRep is ILogged) then
       (aRep as ILogged).Log(aRep.Report)
     else
       aRep.Report
end;

you would have the same effect ?

Necessarily, there is always SOME instance implementing any interface...

Show quoted text 21 lines
Meaning, that if I derived some class as (and call DoReport with it as parameter) type TSomeClass = interface(TInterfacedObject, IReportable, ILogged) this class will have to contain all the logging facility needed, and that's conditioned with interfaces (otherwise it won't be compiled). TSomeClass2 = interface(TInterfacedObject, IReportable) this class will automatically skip logging, because logging interface is not supported by class What is difference here? I could pass a simple interfaced object as parameter and predict possibility of logging. If object or interface support that option then all the facility needed is supported and logging is done. This is how and why interfaces should be used, for predicting features. And with interfaces as they are this is just impossible.

But with a slight change in your code, I think it is, see above ?

If I understand you correct, you want to query the instance 'behind' some interface to see if it inmplements another interface, without having to access the actual instance ?

This still does not explain why you would need to do

   AClassInstance := AnInterface;
( your own obj:=a; statement )
Which seems to me against all pascal rules of strict typing ?

Michael.

Reply by email

memsom
to Michael Van Canneyt

Sorry to be late in the conversation...

Show quoted text 12 lines
> Here is a simple example how it should be used > > type > IReportable = interface > function Report: string; > // let's say that this should write report and > // return status description as string > end; > > ILogged = interface > procedure Log(aStr: string); > end;

Surely, using Delphi's way of things:

  type TMyReport = class(TInterfacedObject, IReportable, ILogged)
         ... //an implementation of each interface
       end;
Show quoted text 8 lines
> procedure MyXYZPart.DoReport(aRep: IReportable); > begin > if (aRep nil) then begin > if (aRep is ILogged) then > (aRep as ILogged).Log(aRep.Report) > else > aRep.Report > end;

Again :

 procedure MyXYZPart.DoReport(aRep: IReportable);
 var
   tmp: ILogged;
 begin
  if (aRep  nil) then begin
    if (aRep.QueryInterface(ILogged, tmp) = S_OK) then
      tmp.Log(aRep.Report) //or you could just do the as cast..
    else
      aRep.Report
 end;
Show quoted text 11 lines
I see what you want, but if you would do procedure MyXYZPart.DoReport(aRep: TInterfacedObject); begin if (aRep nil) and arep is IReportable then begin if (aRep is ILogged) then (aRep as ILogged).Log(aRep.Report) else aRep.Report end;

Converting interfaces to instances to object instances is a bad idea... it screws with reference counting, for a start...> This still does not explain why you would need to do

AClassInstance := AnInterface;

I think the above is a really bad idea. Especially when the implementing class is private... e.g.

interface
type
  IPublic = interface
    procedure whatever;
  end;
  TFactory = class
    function newPublic: IPublic;
  end;
implementation
type
  TPrivate = class(TInterfacedObject, IPublic)
    ...
  end;
  function TFactory.newPublic: IPublic;
  begin
    Result := TPrivate.Create; // or implement some kind of class
                               // pooling etc ..
  end;

How would you be able to get at the class? Only as TObject or TInterfacedObject. Bad idea.

Matt

Reply by email

ml
to memsom
memsom wrote 47 lines
Sorry to be late in the conversation... >> Here is a simple example how it should be used >> >> type >> IReportable = interface >> function Report: string; >> // let's say that this should write report and >> // return status description as string >> end; >> >> ILogged = interface >> procedure Log(aStr: string); >> end; Surely, using Delphi's way of things: type TMyReport = class(TInterfacedObject, IReportable, ILogged) ... //an implementation of each interface end; >> procedure MyXYZPart.DoReport(aRep: IReportable); >> begin >> if (aRep nil) then begin >> if (aRep is ILogged) then >> (aRep as ILogged).Log(aRep.Report) >> else >> aRep.Report >> end; Again : procedure MyXYZPart.DoReport(aRep: IReportable); var tmp: ILogged; begin if (aRep nil) then begin if (aRep.QueryInterface(ILogged, tmp) = S_OK) then tmp.Log(aRep.Report) //or you could just do the as cast.. else aRep.Report end;

1. and what I would like is just a lot cleaner and readable code of this.
2. Before you tell how to do something at least test and look your solution
2.1. Because queryinterface doesn't work in fpc as it should you always get first vmt and if you do a queryinterface you don't work with correct interface, you just get exception when you work with this new interface. Anyway patch for this will be finished until weekend. 2.2. It's ugly and not really readable, you always land with additional declarations like tmp

Show quoted text 18 lines
> I see what you want, but if you would do > > procedure MyXYZPart.DoReport(aRep: TInterfacedObject); > > begin > if (aRep nil) and arep is IReportable then begin > if (aRep is ILogged) then > (aRep as ILogged).Log(aRep.Report) > else > aRep.Report > end; Converting interfaces to instances to object instances is a bad idea... it screws with reference counting, for a start...> This still does not explain why you would need to do

Follow the vmt problems. That is needed for defining blind properties. It has to be redirected to original vmt of class.

For now you have to specify properties as

type
  IA = interface
    function GetSome: integer;
    procedure SetSome(aValue: integer);
    property Some: integer read GetSome write SetSome;
  end;

this is needed because interface has no clue of original vmt. while blind properties definition would be

type
  IA = interface
    property Some: integer read object write object;
  end;

and the implementation of property is left to class, not conditioned with function and procedure

Show quoted text 30 lines
> AClassInstance := AnInterface; I think the above is a really bad idea. Especially when the implementing class is private... e.g. interface type IPublic = interface procedure whatever; end; TFactory = class function newPublic: IPublic; end; implementation type TPrivate = class(TInterfacedObject, IPublic) ... end; function TFactory.newPublic: IPublic; begin Result := TPrivate.Create; // or implement some kind of class // pooling etc .. end;

How could you define private class outside where it is not visible. Best shot for you it would be highest visible type of this class. So sorry, I don't understand this part. This is something which is completely normal behavior and is connected to software plan only. No rocket since here.

How would you be able to get at the class? Only as TObject or TInterfacedObject. Bad idea.

I don't know where the idea here is and thus I don't know why it would be bad.

ml

Show quoted text 9 lines
Matt _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

ml
to Michael Van Canneyt: Hey, the A:=C; was supposed to be the equivalent of YOUR code : // there's no way to do…
Michael Van Canneyt wrote 117 lines
On Thu, 24 Mar 2005, ml wrote: > On Thu, 2005-03-24 at 09:06 +0100, Michael Van Canneyt wrote: >> >> On Thu, 24 Mar 2005 wrote: >> >>> Quoting Michael Van Canneyt : >>> >>>> >>>> >>>> On Wed, 23 Mar 2005 wrote: >>>> >>>>> Quoting Marco van de Voort : >>>>> >>>>>>> On Tue, 22 Mar 2005, ml wrote: >>>>>>>> // than one interface >>>>>>>> a := (object as IA); // correct >>>>>>>> b := (object as IB); // returns pointer to the first interface >>>>> vmt=IA >>>>>>>> c := (object as IC); // returns pointer to the first interface >>>>> vmt=IA >>>>>>>> // there's no way to do again it's like direct call to exception >>>>>>>> obj := a; // returns pointer(obj) + 12 ??? >>>>>>> >>>>>>> This is nonsense. You cannot assign an interface to a class. >>>>>>> A class IMPLEMENTS an interface, it is not an interface. >>>>> >>>>> Ok, its nonsense. I said it already works with my patch, but I guess you >>>>> know it better. So my example down there doesn't work (with patch). You >>>>> should know. >>>>> I (; can't ;) transfer from one interface to other back to object and to >>>>> 3rd interface. I just imagine my results. >>>> >>>> Tell me, what is >>>> >>>> obj := a; >>>> >>>> supposed to DO ? A class has a set of methods. Some of these methods form >>>> the VMT of an interface. What your code does, is say >>>> "don't use your VMT methods, use these instead' ? >>> >>> Yes, exactly. I even provided test example at the bottom of my previous message, >>> where I transfered from class to IA, back to class and then to ID. And called >>> ID.D; And it just works (this is also nice start for blind properties >>> implementation, which now also became possible, since original vmt is now visible) >>> >>> But, It should be used as >>> >>> if (TObject(a).InheritedFrom(TSomeClass)) then begin >>> obj := TSomeClass(a); // note that here obj is declared as TSomeClass >>> // now safely use as this vmt >>> end; >>> >>> if SupportsInterface(TObject(a), IB) then begin >>> ibvar := a; // declared ibvar: IB >>> // now safely use as this vmt >>> end; >>> >>> in perfect world "is" would return InheritedFrom or SupportsInterface result and >>> not actual class check, if true then all needed operations are satisfied. >> >> I can understand that 'is' should be able to check interfaces; this is a >> useful patch. >> >> I also understand what your code should do. >> >> BUT I see some flaws in your design. >> >> IA = Interface >> procedure InitF; >> end; >> >> >> TA = class(TObject,IA) >> F : TList; >> Procedure InitF; >> Procedure B; >> end; >> >> Procedure TA.InitF; >> >> begin >> F:=Tlist.Create; >> end; >> >> Procedure TA.B; >> >> begin >> F.Add(SomePointer); >> end; >> >> >> Var >> A : TA; >> C : IA; >> >> begin > > Completely wrong type of thinking here, and I can't answer you what you > asked, so I provided answer why I can't answer and how it should be used > >> A:=TA.Create; >> C:=SomeIA; // Get an IA interface from somewhere. > > Why would someone create one object just to override its variable with > some other value? To create memory leaks? Hey, the A:=C; was supposed to be the equivalent of YOUR code : // there's no way to do again it's like direct call to exception obj := a; // returns pointer(obj) + 12 ???

:) and that was taken from my first example where I showed problems, I made at least 3 new examples after that (examples how it could be and not showing where the problems are).

Show quoted text 66 lines
? [...] > Here we go again. Your main problem is that you don't understand (or you > lack imagination) what interface is in his complete feature set. Main > feature of interfaces is to have ability to predict combinations of > commands that interfaces support, as I already specified... having > monolithic interface structure makes no sense (you just get mirror copy > of classes), it's a waste of time, paper and space. And before you > answer how it is not possible, or how you don't have time to implement > it. I was not going to answer any of this, I'm trying to understand what you want to accomplish, and why this could be useful for other people. > I'm game. I'm prepared to make all the necessary changes and > patches. All that I would ask for is a few pointers (if that could be > done on line on some irc or msn channel, that would be perfect, it's > hard to talk in one e-mail a day) how and where so that I don't need to > dissect complete compiler code (you probably understand that I'm not as > familiar with its code as you are, that would be only few questions like > "where does it...", "how does it...", "what would be the preffered > implementation of ..."). > > Here is a simple example how it should be used > > type > IReportable = interface > function Report: string; > // let's say that this should write report and > // return status description as string > end; > > ILogged = interface > procedure Log(aStr: string); > end; > > And now some completely different place in your software, main feature > of interfaces is that you can predict possible features, and not even > start to implement them at that moment > > procedure MyXYZPart.DoReport(aRep: IReportable); > begin > if (aRep nil) then begin > if (aRep is ILogged) then > (aRep as ILogged).Log(aRep.Report) > else > aRep.Report > end; I see what you want, but if you would do procedure MyXYZPart.DoReport(aRep: TInterfacedObject); begin if (aRep nil) and arep is IReportable then begin if (aRep is ILogged) then (aRep as ILogged).Log(aRep.Report) else aRep.Report end; you would have the same effect ?

Yeah, exactly like this. And now the bug of this effect. With this you get a whole bunch of calling procedures and functions and all are accepting TInterfacedObject parameter. You don't know what actual parameter is. With passing interfaces as parameters code is much cleaner. And all functions are defined as restrictive what kind of interface is accepted.

Show quoted text 26 lines
Necessarily, there is always SOME instance implementing any interface... > > Meaning, that if I derived some class as (and call DoReport with it as > parameter) > type > TSomeClass = interface(TInterfacedObject, IReportable, ILogged) > > this class will have to contain all the logging facility needed, and > that's conditioned with interfaces (otherwise it won't be compiled). > > TSomeClass2 = interface(TInterfacedObject, IReportable) > > this class will automatically skip logging, because logging interface is > not supported by class > > What is difference here? I could pass a simple interfaced object as > parameter and predict possibility of logging. If object or interface > support that option then all the facility needed is supported and > logging is done. > > This is how and why interfaces should be used, for predicting features. > And with interfaces as they are this is just impossible. But with a slight change in your code, I think it is, see above ?

I see, and I named you reason why. Mostly readability of your code.

If I understand you correct, you want to query the instance 'behind' some interface to see if it inmplements another interface, without having to access the actual instance ?

Yes.

This still does not explain why you would need to do AClassInstance := AnInterface;

The only reason why, is mostly internal (where vmt problems were discussed). If "is" and "as" would be solved as I suggested, this isn't necessary anymore. Meaning I can test if original object (and not interface) implements some other interface and then act as that interface, then this is not necessary anymore.

Having ability to do

  if (aRep is ILogged) then
    (aRep as ILogged).Log(aRep.Report);

would make clean code, where possible calling parameter is obvious

Second reason why could be treated as internal too.

For now you have to specify properties as

type
  IA = interface
    function GetSome: integer;
    procedure SetSome(aValue: integer);
    property Some: integer read GetSome write SetSome;
  end;

this is needed because interface has no clue of original vmt. while blind properties definition would be

type
  IA = interface
    property Some: integer read object write object;
  end;

and the implementation of property is left to class, not conditioned with function and procedure

Follow the vmt problems. That is needed for defining blind properties. Blind property has to be redirected to original vmt of class.

ml

Show quoted text 7 lines
Which seems to me against all pascal rules of strict typing ? Michael. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Michael Van Canneyt
to ml

On Thu, 24 Mar 2005, ml wrote:

[Cut]

Show quoted text 31 lines
> > > > procedure MyXYZPart.DoReport(aRep: IReportable); > > begin > > if (aRep nil) then begin > > if (aRep is ILogged) then > > (aRep as ILogged).Log(aRep.Report) > > else > > aRep.Report > > end; > > I see what you want, but if you would do > > procedure MyXYZPart.DoReport(aRep: TInterfacedObject); > > begin > if (aRep nil) and arep is IReportable then begin > if (aRep is ILogged) then > (aRep as ILogged).Log(aRep.Report) > else > aRep.Report > end; > > you would have the same effect ? > Yeah, exactly like this. And now the bug of this effect. With this you get a whole bunch of calling procedures and functions and all are accepting TInterfacedObject parameter. You don't know what actual parameter is. With passing interfaces as parameters code is much cleaner. And all functions are defined as restrictive what kind of interface is accepted.

OK, now I see where you're going.

Your last sentence means: I want DoReport to accept only an 'IReportable' But at the same time, your code is checking that behind 'IReportable' there is also an 'ILogged'.

I find this a bit contradictory; If you pass an TInterfacedObject, then you can check for as much classes or interfaces as you want. The code remains the same. But this is not a principal question.

More important is: what happens if IReportable is an interface obtained from Windows ? How can you tell whether an interface comes from a Pascal class, or was obtained from a Windows OLE or ActiveX server ? There may not be a a real class behind IReportable. You can construct IReportable interfaces on the fly. (OpenOffice does it, and I think some SOAP implementations as well)

Show quoted text 75 lines
> Necessarily, there is always SOME instance implementing any interface... > > > > > Meaning, that if I derived some class as (and call DoReport with it as > > parameter) > > type > > TSomeClass = interface(TInterfacedObject, IReportable, ILogged) > > > > this class will have to contain all the logging facility needed, and > > that's conditioned with interfaces (otherwise it won't be compiled). > > > > TSomeClass2 = interface(TInterfacedObject, IReportable) > > > > this class will automatically skip logging, because logging interface is > > not supported by class > > > > What is difference here? I could pass a simple interfaced object as > > parameter and predict possibility of logging. If object or interface > > support that option then all the facility needed is supported and > > logging is done. > > > > This is how and why interfaces should be used, for predicting features. > > And with interfaces as they are this is just impossible. > > But with a slight change in your code, I think it is, see above ? > I see, and I named you reason why. Mostly readability of your code. > If I understand you correct, you want to query the instance 'behind' > some interface to see if it inmplements another interface, without > having to access the actual instance ? > Yes. > This still does not explain why you would need to do > > AClassInstance := AnInterface; > The only reason why, is mostly internal (where vmt problems were discussed). If "is" and "as" would be solved as I suggested, this isn't necessary anymore. Meaning I can test if original object (and not interface) implements some other interface and then act as that interface, then this is not necessary anymore. Having ability to do if (aRep is ILogged) then (aRep as ILogged).Log(aRep.Report); would make clean code, where possible calling parameter is obvious Second reason why could be treated as internal too. For now you have to specify properties as type IA = interface function GetSome: integer; procedure SetSome(aValue: integer); property Some: integer read GetSome write SetSome; end; this is needed because interface has no clue of original vmt. while blind properties definition would be type IA = interface property Some: integer read object write object; end; and the implementation of property is left to class, not conditioned with function and procedure

I think the properties are needed, to remain compatible with COM interfaces, which only have methods, I think CORBA has this restriction too; They don't have 'properties'.

After all the discussion, I see 2 real improvements:
- To be able to use 'Is' operator on interfaces.
(so without the need for 'Supports')
- Use 'as' on interfaces. (But this should be possible as in Delphi)

As for querying the class behind the interface: first you need to answer the windows problem.

Michael.

Reply by email

ml
to Michael Van Canneyt
Michael Van Canneyt wrote 10 lines
OK, now I see where you're going. Your last sentence means: I want DoReport to accept only an 'IReportable' But at the same time, your code is checking that behind 'IReportable' there is also an 'ILogged'. I find this a bit contradictory; If you pass an TInterfacedObject, then you can check for as much classes or interfaces as you want. The code remains the same. But this is not a principal question.

Since you agree with "is" and "as". this one is solved too. Maybe you don't see benefits, but "is" and "as" are the only conditions to be able to do what I want. So I guess this doesn't need to be discussed anymore.

Show quoted text 7 lines
More important is: what happens if IReportable is an interface obtained from Windows ? How can you tell whether an interface comes from a Pascal class, or was obtained from a Windows OLE or ActiveX server ? There may not be a a real class behind IReportable. You can construct IReportable interfaces on the fly. (OpenOffice does it, and I think some SOAP implementations as well)

That's what I was asking for. I'm not a windows person and I don't know what problems one could face there.

One solution I see is:

Implementing Me in descedant of IUnknown in IClassUnknown and if interface does not support IClassUnknown instead of calling Me: TObject would just return nil. Meaning class vmt access is not possible and all interface checking is solved trough QueryInterface. After "as" and "is" recognize if interface is classed or not, all problems you named should go away. I maybe have a better way, but I would like to test that one before anyone would start to play nitpick on it.

My question here is: Can I get a simple example of usage to see a problem with windows interfaces, it'll be easier for me to discuss it then?

I think the properties are needed, to remain compatible with COM interfaces, which only have methods, I think CORBA has this restriction too; They don't have 'properties'.

Agreed, but then again new property implementation doesn't exclude old one. Just as
procedure ... of object;
here could be
property ... read object write object; // or something like this or
property ... read CallFunc write CallProc;

So if it doesn't break compatibility, what else could one expect Here (word) object would just relink property on creation to the vmt of original class (see comment down on not breaking OLE or ActiveX).

After all the discussion, I see 2 real improvements: - To be able to use 'Is' operator on interfaces. (so without the need for 'Supports') - Use 'as' on interfaces. (But this should be possible as in Delphi)

I'll test Delphi, but I own v.5 (and have yet to set one windows box to test on). Will this do?

As for querying the class behind the interface: first you need to answer the windows problem.

As soon as I finish my patch for "as" and "is" I'll implement it so that it will handle distinction between IUnknown and IClassUnknown (if needed, as soon as I get example to test on, I'll know what to test for, I'll try to look for some ActiveX or OLE example, but I know only where to find Delphi stuff, will testing on Delphi examples suffice?) and send patch here.

ml

Show quoted text 5 lines
Michael. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

memsom
to ml: 1. and what I would like is just a lot cleaner and readable code of this. 2. Before you…
Show quoted text 10 lines
1. and what I would like is just a lot cleaner and readable code of this. 2. Before you tell how to do something at least test and look your solution 2.1. Because queryinterface doesn't work in fpc as it should you always get first vmt and if you do a queryinterface you don't work with correct interface, you just get exception when you work with this new interface. Anyway patch for this will be finished until weekend. 2.2. It's ugly and not really readable, you always land with additional declarations like tmp

FPC is wrong. To be Delphi compatible, you need IS to work as well as QueryInterface. I'm not interested in your suggestion, it's non standard and will cause a break in compatibility...

Follow the vmt problems. That is needed for defining blind properties. It has to be redirected to original vmt of class.

Absolutely not!!!! Blind properties will break Delphi compatibility. Also... remember the property you define in the interface is NOT the same as the one you define in the class. Indeed, you need not defire the property in the class, or can make the property in the interface readonly, for example.

Show quoted text 19 lines
For now you have to specify properties as type IA = interface function GetSome: integer; procedure SetSome(aValue: integer); property Some: integer read GetSome write SetSome; end; this is needed because interface has no clue of original vmt. while blind properties definition would be type IA = interface property Some: integer read object write object; end; and the implementation of property is left to class, not conditioned with function and procedure

This is hideous!! I *WANT* to define the property in the interface. That is the whole point!!! Otherwise, how can I do this:

 type
   IA = interface
     function GetSome: integer;
     property Some: integer read GetSome;
     procedure ALittle;  //state machine
     procedure SomeMore; //some is moved through
     procedure ALot;     //three states
   end;
   TA = class(TInterfacedPersistent, IA)
   private
     function GetSome: integer;
     procedure SetSome(aValue: integer);
   published
     property Some: integer read GetSome write SetSome; //for streaming
   end;

Simply, you will not be able to do this in the same way!!! Remember, an interface is a pure abstract class in reality!!

Another question:

type IA = interface property Some: integer read object write object; end;

This implies I must have a property called "Some", however, I commonly do the following:

   IA = interface
     function GetSome: integer;
     procedure SetSome(aValue: integer);
     property Some: integer read GetSome;
   end;
   TA = class(TInterfacedPersistent, IA)
   private
     function GetSome: integer;
     procedure SetSome(aValue: integer);
   published
     property A1289: integer read GetSome write SetSome; //for streaming
   end;

"A1289" is obstificated to hide its meaning within the streaming mechanism. This used to be important because the company I was working with had a product, which used an Object persistence mechanism using RTTI, that we inherited from the products former supplier. We effectively "forked" the code because the two companies split appart their partnership in a less than amicable break up of a company releationship. Each company continued development on the product. We purpousfully obstificated our new properties to give them no clues on how to interpret our data if they attempted to take over one of our customer sites. This is purely political, but also remember that when storing a streamed class, delphi stored the property name. I'd prefer a meaningful name in my code, e.g. IPublic.YearlyProfitMargin, but a shorter name in streaming to save room, i.e. TPrivate.YPM. Does that make sense? If you store 1 of those classes, the size is negligable. However, store 100000 and the difference is notable in real disk space.

In truth we would do the following:

   TA = class(TInterfacedPersistent, IA)
   private
     function GetSome: integer;
     procedure SetSome(aValue: integer);
   public
     property INF_some: integer read GetSome write SetSome;
   published
     property A1289: integer read GetSome write SetSome; //for streaming
   end;

How does that fit with your plans??? Not so simple is it? ;-) Dual properties are perfectly legal. A1289 will NEVER be used in code. It's there for streaming alone.

How could you define private class outside where it is not visible. Best shot for you it would be highest visible type of this class. So sorry, I don't understand this part. This is something which is completely normal behavior and is connected to software plan only. No rocket since here.

Read the code. The TPrivate class is controlled by the TFactory. The TPrivate class is defined in the implementation secton of the unit - it is PRIVATE to the unit. You access it via the interface IPublic, returned via the TFactory.newXXX call. You are aware of encapsulation, arent you? Also, design patterns.

Show quoted text 6 lines
> > How would you be able to get at the class? Only as TObject or > TInterfacedObject. Bad idea. I don't know where the idea here is and thus I don't know why it would be bad.

Encapslation. The provate implementation can change, or can be replaced without code changes. This is just like using inline classes in Java, really.

Matt

Reply by email

Marcel Martin
to Michael Van Canneyt: Hey, the A:=C; was supposed to be the equivalent of YOUR code : // there's no way to do…
Michael Van Canneyt wrote 25 lines
>> On Thu, 24 Mar 2005 wrote: > > procedure MyXYZPart.DoReport(aRep: IReportable); > begin > if (aRep nil) then begin > if (aRep is ILogged) then > (aRep as ILogged).Log(aRep.Report) > else > aRep.Report > end; I see what you want, but if you would do procedure MyXYZPart.DoReport(aRep: TInterfacedObject); begin if (aRep nil) and arep is IReportable then begin if (aRep is ILogged) then (aRep as ILogged).Log(aRep.Report) else aRep.Report end; you would have the same effect ?

Yes, in both cases, the compiler will stop because of a "begin" without a "end". ;-)

More seriously, each time I see a "then begin", maybe I am wrong but I immediately think that I have to deal with some code written by a C programmer. And, curiously, I cannot find it reassuring.

mm

Reply by email

ml
to Marcel Martin

I made one wrong statement.

It's not "as" that doesn't work. getinterfaceentry works only for interfaces that have guid specified. By default guid is zeroed, and getinterfaceentry just returns first interface in table, which means wrong. Same problem shows in Support too.

writing guid like ['{00000001-0001-0001-C000-000000340046}'] in interfaces definition made it work as it should.

As soon as I set counter for auto defining guid (only if blank) in symdef.pas, everything works even without specifying . (if guid is specified then specified is used), otherwise it decrements from highest possible to lowest. If this would be to stay then I can send this patch. It doesn't break compilation of any older source. But i don't know if some interfaces already use that GUID.

Any better suggested approach? (Second possible solution would be implementing some other checking that's invoked if guid is 0) I am not familiar with what guid would be (I suspect that it has some higher meaning in windows, because all windows interfaces are specified with guid, now even m$ stopped using specified guid in .net), so I would appreciate some help by suggesting. And yes, this is a bug not a feature.

Marcel Martin wrote 31 lines
Michael Van Canneyt wrote: >>> On Thu, 24 Mar 2005 wrote: >> >> procedure MyXYZPart.DoReport(aRep: IReportable); >> begin >> if (aRep nil) then begin >> if (aRep is ILogged) then >> (aRep as ILogged).Log(aRep.Report) >> else >> aRep.Report >> end; > > > I see what you want, but if you would do > > procedure MyXYZPart.DoReport(aRep: TInterfacedObject); > > begin > if (aRep nil) and arep is IReportable then begin > if (aRep is ILogged) then > (aRep as ILogged).Log(aRep.Report) > else > aRep.Report > end; > > you would have the same effect ? Yes, in both cases, the compiler will stop because of a "begin" without a "end". ;-)

That's the punishment you get when you copy/paste from source to write less. Yes, my bad.

Show quoted text 5 lines
More seriously, each time I see a "then begin", maybe I am wrong but I immediately think that I have to deal with some code written by a C programmer. And, curiously, I cannot find it reassuring.

Actually first company I was employed was using pascal. And they enforced "then begin" and other rules. Somehow I can't stop writing like this

when I write in c or c#, I write like this

if ( a == 1 )
{

	return;

}

And there's a very few coders that write
if (a==1) {

Show quoted text 8 lines
mm _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Thomas Schatzl
to ml

Hello,

Show quoted text 6 lines
I made one wrong statement. It's not "as" that doesn't work. getinterfaceentry works only for interfaces that have guid specified. By default guid is zeroed, and getinterfaceentry just returns first interface in table, which means wrong. Same problem shows in Support too.

Hmmm, Delphi gives a compile time error if "as" is used on an interface without GUID, same for support()... since both use the interfaces IID to query for existence of an interface (either directly or via QueryInterface of IUnknown).

Show quoted text 5 lines
Any better suggested approach? (Second possible solution would be implementing some other checking that's invoked if guid is 0) I am not familiar with what guid would be (I suspect that it has some higher meaning in windows, because all windows interfaces are specified with guid, now even m$ stopped using specified guid in .net), so I would

The GUID (=UUID) uniquely identifies a COM interface. A .net interface is not a COM interface, it's more a language construct like in Java. By some wrapping any(?) .net interface can be used as COM interface afaik (and the other way round) though.
.net provides more advanced means of querying run-time type information than the ones available in Object Pascal, e.g. it likely does not need to rely on a GUID for these types of operation, so there's no need to specify this by default.

Btw, to implement unnamed properties of (non-COM) interfaces (as the one available in objfpc mode) there's imo need for more sophisticated rtti; e.g. so that this would work, you'd need a way to query the read and write methods of the particular class of the instance and call them. Neither querying of properties nor getting info on the read/write methods of properties is possible atm since Object Pascal does not store this info anywhere by default afaik (for all visibility types of properties, for all Pascal objects).
[Maybe I'm wrong, I'm not so into rtti]

appreciate some help by suggesting. And yes, this is a bug not a feature.

Either automatically create a good GUID for the interface (there should be a CreateGUID() method in fpc), or error out like Delphi (to be compatible).

Regards,
Thomas

Reply by email

Unknown author
to Thomas Schatzl

Quoting Thomas Schatzl :

Show quoted text 9 lines
Hello, ml schrieb: Hmmm, Delphi gives a compile time error if "as" is used on an interface without GUID, same for support()... since both use the interfaces IID to query for existence of an interface (either directly or via QueryInterface of IUnknown).

This is doable, patch can contain both with compiler directive for selection (ok, usage of compiler error is not done yet). One other possibility is checking some IClassUnknown (inherited from IUnknown) support and auto assign guid (at least if not defined in interface) to it. If it is not, then interface is either COM or Corba and should be left alone so that interface doesn't break anything. If interface is derived from this IClassUnknown, then this means that:
1. class object is present
2. not corba or com

In fpc sources there's a comment
if guid is 0 then corba_interface otherwise com_interface (I don't have my notebook here so this is not copy pasted from source, just the meaning). Are corba interfaces really guid 0 (if that would be the case then support and as wouldn't work on corba interfaces in Delphi), or is that comment just outdated?

Show quoted text 10 lines
> Any better suggested approach? (Second possible solution would be > implementing some other checking that's invoked if guid is 0) I am not > familiar with what guid would be (I suspect that it has some higher > meaning in windows, because all windows interfaces are specified with > guid, now even m$ stopped using specified guid in .net), so I would The GUID (=UUID) uniquely identifies a COM interface. A .net interface is not a COM interface, it's more a language construct like in Java. By some wrapping any(?) .net interface can be used as COM interface afaik (and the other way round) though.

Yes, but COM object must load .net dll and create new interface

Show quoted text 5 lines
.net provides more advanced means of querying run-time type information than the ones available in Object Pascal, e.g. it likely does not need to rely on a GUID for these types of operation, so there's no need to specify this by default.

No it doesn't. Nice example is using CILC (exists on mono) on dll that provides interfaces. CILC produces c headers and library for accessing .net dlls. don't know if it works ms .net (it probably should).

Show quoted text 10 lines
Btw, to implement unnamed properties of (non-COM) interfaces (as the one available in objfpc mode) there's imo need for more sophisticated rtti; e.g. so that this would work, you'd need a way to query the read and write methods of the particular class of the instance and call them. Neither querying of properties nor getting info on the read/write methods of properties is possible atm since Object Pascal does not store this info anywhere by default afaik (for all visibility types of properties, for all Pascal objects). [Maybe I'm wrong, I'm not so into rtti]

It is doable and in my plan. But I suspect it will just stay my own patch for me and whoever wants it (as some others interface patches of mine, like multiple inheritance).

Show quoted text 7 lines
> appreciate some help by suggesting. And yes, this is a bug not a > feature. Either automatically create a good GUID for the interface (there should be a CreateGUID() method in fpc), or error out like Delphi (to be compatible).

and good guid would be? If I remember correctly I saw GUID calculator for Delphi but I don't remember where and if method implemented was official way of calculating GUID (if this exists).
for now I just assign max possible interface and decrement for every type.

Regards, Thomas

thanks
ml

_______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

---------------------------------------------------------------------- This mail sent through Horde-Toaster (http://qmailtoaster.clikka.com/)

Reply by email

Thomas Schatzl
to Unknown author

Hello,

note in advance: if I mention CORBA interfaces, I actually mean "CORBA style" or Java/.net like interfaces (which are not real CORBA interfaces anyway) in the following (too lazy to do a search&replace or find another term).

Show quoted text 8 lines
>ml schrieb: >Hmmm, Delphi gives a compile time error if "as" is used on an interface > [...] > This is doable, patch can contain both with compiler directive for selection (ok, usage of compiler error is not done yet). One other possibility is checking some IClassUnknown (inherited from IUnknown) support and auto assign guid (at least if not defined in interface) to it.

This check for COM-interfaces could be done on compile time saving runtime (and code, and... :) if supports() or as is used in the code. Or simply automatically assign a reasonable GUID for every COM interface (probably easier =)

I don't know if checking for some class IClassUnknown is actually required...
Maybe handle operators for CORBA interfaces completely differently (the compiler already recognizes the type of the interface at compile time from what I can see from the compiler code).

E.g. avoid using standard QueryInterface() (which may not be available for CORBA interfaces anyway) for this type and completely rely on other means for that.

But this would require more compiler tinkering.

Show quoted text 5 lines
In fpc sources there's a comment if guid is 0 then corba_interface otherwise com_interface (I don't have my notebook here so this is not copy pasted from source, just the meaning). Are corba interfaces really guid 0 (if that would be the case then support and as wouldn't work on corba interfaces in Delphi)

This is not true, since COM interfaces which don't have a GUID assigned also have the default zero GUID.

But interfaces support seems to be at least partially broken for both COM and CORBA interfaces, especially the supports() and "as" operators (in the 1.9.8 compiler).

Show quoted text 13 lines
>Btw, to implement unnamed properties of (non-COM) interfaces (as the one >available in objfpc mode) there's imo need for more sophisticated rtti; >e.g. so that this would work, you'd need a way to query the read and >write methods of the particular class of the instance and call them. >Neither querying of properties nor getting info on the read/write >methods of properties is possible atm since Object Pascal does not store >this info anywhere by default afaik (for all visibility types of >properties, for all Pascal objects). >[Maybe I'm wrong, I'm not so into rtti] It is doable and in my plan. But I suspect it will just stay my own patch for me and whoever wants it (as some others interface patches of mine, like multiple inheritance).

Actually I'd love to see a more complete RTTI in Pascal (say, e.g. in OBJFPC mode), not minding the increased binary sizes (maybe optional). Although I don't need it very often, the introspection information offered by Delphi is quite limited (e.g. exactly to the explicitely published things which Borland needed for the IDE).

Btw, MI for interfaces is completely fine for Corba interfaces, I had a peek at the spec (well, I needed it for other things too ;). E.g. it's completely fine to specify this:

interface A { ... }
interface B: A { ... }
interface C: A { ... }
interface D: B, C { ... }
interface E: A, B { ... };

[From the Corba core spec, v3.0: interface declaration, pg. 3-23]

Since an interface is only a specification without implementation I don't see any troubles concerning multiple inheritance as pointed out in another message of this thread (going towards Java/c# like interfaces).

Some additional safety things should be put into place to not allow mixing them though (e.g. similar to not allow mixing old style objects with new style classes).

Show quoted text 9 lines
>>appreciate some help by suggesting. And yes, this is a bug not a >>feature. > >Either automatically create a good GUID for the interface (there should >be a CreateGUID() method in fpc), or error out like Delphi (to be >compatible). and good guid would be? If I remember correctly I saw GUID calculator for Delphi

Ones created by CreateGUID()? =)

but I don't remember where and if method implemented was official way of calculating GUID (if this exists).

I think there's an RFC out there to calc UUIDs (which is the same as a GUID) for DCE/RPC or so. But as far as I'm concerned it should be fine to rely on the OS for that.
Usually part of the RPC implementation - for Windows I know that RPC is used in any version. In case of some Unix (or other OS), if the required libs are not available (can't really imagine that there's no standard RPC implementation for that), use a good 128 bit random number from somewhere.

for now I just assign max possible interface and decrement for every type.

This is bad, because this GUID is stored in every ppu file for the types too. So if you use some external lib they will certainly clash (actually I think they already do, probably making using interfaces quite interesting for the person who debugs that code =)

But all this is only my personal opinion about this issue.

Regards,
Thomas

Reply by email

Unknown author
to Thomas Schatzl

Quoting Thomas Schatzl :

Show quoted text 27 lines
Hello, note in advance: if I mention CORBA interfaces, I actually mean "CORBA style" or Java/.net like interfaces (which are not real CORBA interfaces anyway) in the following (too lazy to do a search&replace or find another term). schrieb: >>ml schrieb: >>Hmmm, Delphi gives a compile time error if "as" is used on an interface >> [...] >> > This is doable, patch can contain both with compiler directive for selection > (ok, usage of compiler error is not done yet). One other possibility is checking > some IClassUnknown (inherited from IUnknown) support and auto assign guid (at > least if not defined in interface) to it. This check for COM-interfaces could be done on compile time saving runtime (and code, and... :) if supports() or as is used in the code. Or simply automatically assign a reasonable GUID for every COM interface (probably easier =) I don't know if checking for some class IClassUnknown is actually required...

it is for my other feature (converting interface vmt to original class vmt, it was said that some com or corba objects don't have asociated object, so you can't transfer to classes vmt because class object is not present. with IClassUnknown I know that interface is completely handled by fpc.

this is needed for support for, here you need run-time calculateded interface vmt property SomeList: TSomeList read FSomeList implements ISomeList;
- This is present from delphi 4, but not supported in fpc as for the other idea I have in mind
property A: integer read object write object;
property or function aliases aren't in my interests so they probably won't be done, at least by me),
i don't want to break any incompatibility with any fpc compilable source.

Show quoted text 8 lines
Maybe handle operators for CORBA interfaces completely differently (the compiler already recognizes the type of the interface at compile time from what I can see from the compiler code). E.g. avoid using standard QueryInterface() (which may not be available for CORBA interfaces anyway) for this type and completely rely on other means for that.

corba will have its time, but first i'd like to finish features more needed by me

Show quoted text 49 lines
But this would require more compiler tinkering. > In fpc sources there's a comment > if guid is 0 then corba_interface otherwise com_interface (I don't have my > notebook here so this is not copy pasted from source, just the meaning). Are > corba interfaces really guid 0 (if that would be the case then support and as > wouldn't work on corba interfaces in Delphi) This is not true, since COM interfaces which don't have a GUID assigned also have the default zero GUID. But interfaces support seems to be at least partially broken for both COM and CORBA interfaces, especially the supports() and "as" operators (in the 1.9.8 compiler). >>Btw, to implement unnamed properties of (non-COM) interfaces (as the one >>available in objfpc mode) there's imo need for more sophisticated rtti; >>e.g. so that this would work, you'd need a way to query the read and >>write methods of the particular class of the instance and call them. >>Neither querying of properties nor getting info on the read/write >>methods of properties is possible atm since Object Pascal does not store >>this info anywhere by default afaik (for all visibility types of >>properties, for all Pascal objects). >>[Maybe I'm wrong, I'm not so into rtti] > > It is doable and in my plan. But I suspect it will just stay my own patch for me > and whoever wants it (as some others interface patches of mine, like multiple > inheritance). Actually I'd love to see a more complete RTTI in Pascal (say, e.g. in OBJFPC mode), not minding the increased binary sizes (maybe optional). Although I don't need it very often, the introspection information offered by Delphi is quite limited (e.g. exactly to the explicitely published things which Borland needed for the IDE). Btw, MI for interfaces is completely fine for Corba interfaces, I had a peek at the spec (well, I needed it for other things too ;). E.g. it's completely fine to specify this: interface A { ... } interface B: A { ... } interface C: A { ... } interface D: B, C { ... } interface E: A, B { ... };

I know that, but nor Delphi neither fpc support MI. I'd like to implement it as add-on patch (when finished it will be downloadable from my site). Somehow got the feeling that people don't wan't more, even though it doesn't break anything.

Show quoted text 6 lines
[From the Corba core spec, v3.0: interface declaration, pg. 3-23] Since an interface is only a specification without implementation I don't see any troubles concerning multiple inheritance as pointed out in another message of this thread (going towards Java/c# like interfaces).

Yes there is a problem. It looks like some people would like to crucify me because I try to think out of borland. Even though I specified that this will be outside patches (can be included if wished) and they won't break anything.

And second problem is that fpc does interfacing the wrong way. Interfaces stack vmt one on another and report offset of children when inheriting, which is sensible when you talk classes, but unfortunatelly this is plain wrong if you want to do multiple interfaces.

multiple interfaces don't stack vmts (actualy in any other open source language they don't do that. I don't know for delphi though). They just pose another vmt as dependancy, because there is no overloading and no virtualizing.

having (for example down here)
IA > function A: integer;
IB > function A: integer;
IC > function A: integer;
ID > function A: integer;
doesn't request four implementations in class. So every vmt is self sustainable.
It just has to be posed as needed

MI just poses list of interfaces and his own functions and properties.

in simple logic

type
  IA = interface(IB, IC, ID)

Correct MI handling is like this: IA definition has specified only his own functions in his vmt + additional vmt needs. But when object does

type
  TA = class(TInterfacedObject, IA)

this just gets translated to

TA = class(TInterfacedObject, IA + what IA needs)
TA = class(TInterfacedObject, IA, IB, IC, ID)

when calling Support for MI.

1.Check support (IA)
2.Check is IA has needed interfaces
3.Check support for every needed interface in IA list 4.If all conditions satisfied then true

Show quoted text 17 lines
Some additional safety things should be put into place to not allow mixing them though (e.g. similar to not allow mixing old style objects with new style classes). >>>appreciate some help by suggesting. And yes, this is a bug not a >>>feature. >> >>Either automatically create a good GUID for the interface (there should >>be a CreateGUID() method in fpc), or error out like Delphi (to be >>compatible). > > > and good guid would be? If I remember correctly I saw GUID calculator for Delphi Ones created by CreateGUID()? =)

didn't look at that, does fpc have createguid

Show quoted text 12 lines
> but I don't remember where and if method implemented was official way of > calculating GUID (if this exists). I think there's an RFC out there to calc UUIDs (which is the same as a GUID) for DCE/RPC or so. But as far as I'm concerned it should be fine to rely on the OS for that. Usually part of the RPC implementation - for Windows I know that RPC is used in any version. In case of some Unix (or other OS), if the required libs are not available (can't really imagine that there's no standard RPC implementation for that), use a good 128 bit random number from somewhere.

i searched but i can't find rfc for calculating guid. md5sum should probably suffice

Show quoted text 6 lines
> for now I just assign max possible interface and decrement for every type. This is bad, because this GUID is stored in every ppu file for the types too. So if you use some external lib they will certainly clash (actually I think they already do, probably making using interfaces quite interesting for the person who debugs that code =)

yeah, I knew it was bad, but it was a temporary quickfix solution. that's why i was asking, 128/bit md5 sum from "unit.interfacename" should probably do the trick

Show quoted text 11 lines
But all this is only my personal opinion about this issue. Regards, Thomas _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

---------------------------------------------------------------------- This mail sent through Horde-Toaster (http://qmailtoaster.clikka.com/)

Reply by email