Lazarus

Free Pascal => Beginners => Topic started by: syntonica on December 05, 2019, 02:28:18 pm

Title: Interfaces/Polymorphism
Post by: syntonica on December 05, 2019, 02:28:18 pm
I'm just beginning to learn Pascal (again...) and the OO part is confusing me!

What I want is an interface (as in Java) or an abstract class (as in C++) where I have several classes implementing them.

Type
ParentInterface = Interface...
....

ChildClass1 = Class...
...

ChildClass2 = Class...
...

Now, what I need is a pointer that's declared as Type ParentInterface, but can hold an instance of either ChildClass1 or ChildClass2. Is this how Pascal works? If not, do I go for a virtual class instead? I've tried reading the docs, but they're still rather opaque to me at this point.

Sorry for the brevity of my code example, but I'm only as far as "Hello, World" at this point, but I learn best by taking on a large project and working it out step by step. My goal is to ultimately maybe use Pascal instead of C++ for audio DSP development.


Title: Re: Interfaces/Polymorphism
Post by: Thaddy on December 05, 2019, 03:09:00 pm
Does this help?
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$R+}
  2. type
  3.  THello = class
  4.  public
  5.    Function WhoAmI:string;virtual;
  6.  end;
  7.  
  8.  TWorld = class(THello)
  9.  public
  10.    Function WhoAmI:string;override;
  11.  end;
  12.  
  13.  Function THello.WhoAmI:string;
  14.  begin
  15.    write('Hello');
  16.  end;
  17.  
  18.  Function TWorld.WhoAmI:string;
  19.  begin
  20.    inherited;
  21.    write(', World');
  22.  end;
  23.  
  24. var
  25.  a:THello;
  26.  b:TWorld;
  27. begin
  28.  a:=THello.Create;
  29.  writeln(a.WhoAmI);
  30.  a.free;
  31.  b:=TWorld.Create;
  32.  writeln(b.WhoAmI);
  33.  b.free;
  34. end.
Title: Re: Interfaces/Polymorphism
Post by: devEric69 on December 05, 2019, 03:19:18 pm
What is important to understand, is that there is no garbage collector in Pascal (in Pascal, we destroy what we've created). So, the use of abstraction is more "natural" than the use of interfaces in Pascal.

You can have a look at this discussion, about using the interfaces in a Pascal context: https://forum.lazarus.freepascal.org/index.php/topic,46181.msg328478.html#msg328478 (https://forum.lazarus.freepascal.org/index.php/topic,46181.msg328478.html#msg328478) .

Title: Re: Interfaces/Polymorphism
Post by: syntonica on December 05, 2019, 04:04:17 pm
Does this help?

Not quite, but thank you very much for the prototype!

Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$R+}
  2. type
  3.  THello = class
  4.  public
  5.    Function WhoAmI:string;virtual;
  6.  end;
  7.  
  8.  TWorld = class(THello)
  9.  public
  10.    Function WhoAmI:string;override;
  11.  end;
  12.  
  13.  Function THello.WhoAmI:string;
  14.  begin
  15.    write('Hello');
  16.  end;
  17.  
  18.  Function TWorld.WhoAmI:string;
  19.  begin
  20.    { inherited; }
  21.    write(', World');
  22.  end;
  23.  
  24. var
  25.  a:THello;
  26.  { b:TWorld; }
  27. begin
  28.  a:=THello.Create;
  29.  writeln(a.WhoAmI);
  30.  a.free;
  31.  
  32.  a:=TWorld.Create;  { <-this was my question here }
  33.  writeln(a.WhoAmI);
  34.  a.free;
  35.  
  36. end.
  37.  
Output:
"Hello
, World"
This worked as I hoped! C++-style FTW!  :D

My first project will be porting over my VST plugin from C++ for both Mac and Windows and there are a few changes I want to make at the very core that depend on polymorphism.  And I have to say, the ability to cross-compile might mean I only have to do final testing on the PC, no more programming!  Now, to see if I can get over Pascal's wordiness...

Last question to whomever is reading this: Is the a coding style manual or list of things you really should/shouldn't do?  I notice T's for types and I's for interfaces, etc., as well as different casing.

(Edit: fixed my bad copypasta.)
Title: Re: Interfaces/Polymorphism
Post by: syntonica on December 05, 2019, 04:08:36 pm
What is important to understand, is that there is no garbage collector in Pascal (in Pascal, we destroy what we've created). So, the use of abstraction is more "natural" than the use of interfaces in Pascal.

You can have a look at this discussion, about using the interfaces in a Pascal context: https://forum.lazarus.freepascal.org/index.php/topic,46181.msg328478.html#msg328478 (https://forum.lazarus.freepascal.org/index.php/topic,46181.msg328478.html#msg328478) .

Thanks for the reply, but I'm really unsure why GC is relevant here. In C++, I new/delete and in Pascal, it looks like it'll be Create/Free.
Title: Re: Interfaces/Polymorphism
Post by: kupferstecher on December 05, 2019, 04:54:12 pm
Code: Pascal  [Select][+][-]
  1. var
  2.  a:THello;
  3.  { b:TWorld; }
  4. begin
  5.  a:=THello.Create;
  6.  writeln(a.WhoAmI);
  7.  a.free;
  8.  
  9.  a:=TWorld.Create;  { <-this was my question here }
  10.  writeln(b.WhoAmI);
  11.  a.free;
  12.  
  13.  
It's should be mentioned, that the variable "a" is a reference to the instance only. So the below is legit code.

Code: Pascal  [Select][+][-]
  1. a:=THello.Create;
  2. b:= a;
  3. b.WhoAmI;
  4. b.free;
  5.  
Title: Re: Interfaces/Polymorphism
Post by: mtournay on December 05, 2019, 05:17:51 pm

this should help

https://castle-engine.io/modern_pascal_introduction.html
Title: Re: Interfaces/Polymorphism
Post by: marcov on December 05, 2019, 08:26:53 pm
Thanks for the reply, but I'm really unsure why GC is relevant here. In C++, I new/delete and in Pascal, it looks like it'll be Create/Free.

Probably because the most used form of interfaces is reference counted. ("smart pointer").
Title: Re: Interfaces/Polymorphism
Post by: syntonica on December 05, 2019, 10:24:53 pm
Thanks for the reply, but I'm really unsure why GC is relevant here. In C++, I new/delete and in Pascal, it looks like it'll be Create/Free.

Probably because the most used form of interfaces is reference counted. ("smart pointer").

Oh! Okay! I was hoping I wasn't missing anything and it looks like I was, sort of. I'll have to watch out for that since I prefer malloc/free over RC.

I've decided how I'm going to proceed here and step one is to port over my graphics/UI engine written in GDI/Cocoa since:
1) I can't find any library that's similar, and
2) If this doesn't scare me away from Pascal, nothing will!
If it's a success, I will definitely share the unit and it will be my contribution to putting another stake in the heart of Carbon. If it had been written in anything other than Pascal, wouldn't we all be Cocoaized by now?

Title: Re: Interfaces/Polymorphism
Post by: Thaddy on December 06, 2019, 04:04:09 am
My first project will be porting over my VST plugin from C++ for both Mac and Windows and there are a few changes I want to make at the very core that depend on polymorphism.  And I have to say, the ability to cross-compile might mean I only
I actually did quite a lot of VST programming in Pascal (the first Pascal VST host was written by me and subs. improved by TobyBear and Christian, I also translated FreeVerb3 by Yezar to Pascal and quite a bit more original ones) so Yes, VST plugins and hosts are perfectly feasible. Christian wrote a very nice framework for it, based on my and subs. TobyBear's work. Also note some of the people from FL studio independently did the same thing: Fruity loops was basically written in Delphi and some of the original programmers are forum members. As is Christian.

So for sure, VST questions can be answered here as long as they are Pascal related.
Title: Re: Interfaces/Polymorphism
Post by: syntonica on December 06, 2019, 06:17:10 am
by TobyBear

So for sure, VST questions can be answered here as long as they are Pascal related.

I've got his VST 2.3 SDK Pascal translation lying around here somewhere. I'll have to update it to 2.4, but most of the heavy lifting is done.

I've been trying little tests comparing bespoke functions that I'll know I'll be needing in a head-to-head C vs. Pascal battle. C was winning by a significant amount until I discovered the -CSSE3 switch, which put Pascal into the lead! (against GCC -Ofast.)

One thing I've been surprised by is that, so far, orthography aside, Pascal is far more elegant and expressive than C. C libraries seem to have been designed by sadomasochists (which I thought was the realm of C++ designers.) I'm constantly hammering at a nail with screwdrivers, pliers and saws, where Pascal seems to always hands me just the right size hammer for the job.
Title: Re: Interfaces/Polymorphism
Post by: Thaddy on December 06, 2019, 09:02:59 am
I've got his VST 2.3 SDK Pascal translation lying around here somewhere. I'll have to update it to 2.4, but most of the heavy lifting is done.
That's already done. Even the latest SDK is already translated /flattened to Pascal. Important for synth plugins. Effects are perfectly OK in lower versions. Note the newer versions seem to be slower, more hardware demanding.
And I forgot the mention Frederic VanMol, who did the first translation for the VST client SDK and upon his work everything else is based. (But he worked/works for FL Studio) And I did the first host.

About speed:
There really is no difference, since most VST's are optimized with (B)ASM code anyway: you may be surprised though, that FPC actually performs better than Delphi because it has better FPU support, depending on processor type, of course. And with the correct settings. ( -Cf<XXX> ). Funny that here it actually pays off to use FPC instead of C++.
FPC can be highly efficient on vector processing (buffer calculations included) if you know how to handle processor specific optimizations.

When using the LLVM back-end the results should be even better - completely equal to llvm C++ -, although I did not write a VST since 7 years.
Title: Re: Interfaces/Polymorphism
Post by: syntonica on December 06, 2019, 09:23:12 am
I've got his VST 2.3 SDK Pascal translation lying around here somewhere. I'll have to update it to 2.4, but most of the heavy lifting is done.
That's already done. Even the latest SDK is already translated /flattened to Pascal. Important for synth plugins. Effects are perfectly OK in lower versions. Note the newer versions seem to be slower, more hardware demanding.
And I forgot the mention Frederic VanMol, who did the first translation for the VST client SDK and upon his work everything else is based. (But he worked/works for FL Studio) And I did the first host.
My Google Fu must be lacking, as I had to scrape to get the 2.3 version....  :) Can you point me in the right direction?
Title: Re: Interfaces/Polymorphism
Post by: marcov on December 06, 2019, 10:05:30 am
Probably because the most used form of interfaces is reference counted. ("smart pointer").

Oh! Okay! I was hoping I wasn't missing anything and it looks like I was, sort of. I'll have to watch out for that since I prefer malloc/free over RC.

Interface problems are largely due to RC. Mostly because most have a trial and error way of working, which usually aligns well with Pascal/Delphi, but this is an exception :-)

This because only interface references are automatically refcounted and the corresponding object references are not. They have a ref count for interface usage (the last reference via an interface disappearing will deallocate), but object references does.

As manual vs refcounted goes, in general I'm pro manual allocation, but not a purist, IOW they will have to pry refcounting strings from my cold, dead hands :-)   

Quote
If it's a success, I will definitely share the unit and it will be my contribution to putting another stake in the heart of Carbon. If it had been written in anything other than Pascal, wouldn't we all be Cocoaized by now?

Cocoa had a name of being buggy and having versioning problems for a long time. Also it was not a plain C app, so a lot of Objective C interfacing had to be arrange to make it practical. (you did check out the objective Pascal dialect didn't you?) . It also was an enormous amount of work, and little comparison material.

Carbon just worked, and was usable as fundament for long term libraries and frameworks. Even Adobe postponed the migration several times ( and eventually went with a cloud version)

Note that since development versions of Lazarus have a cocoa port, lazarus LCL is a form of GDI/cocoa abstraction already. Rebasing your framework on top of it could be worthwhile

p.s. the cloud thing is a joke, I don't think that is related to cocoa.
Title: Re: Interfaces/Polymorphism
Post by: avra on December 06, 2019, 10:11:55 am
My first project will be porting over my VST plugin from C++ for both Mac and Windows
There is pl_AsioVST package which you can install via OPM which can help you to create VST plugins or ASIO applications. There are many included built in filters to built effects without much DSP knowledge. I am not quite sure, but I think it's only for Windows. It's a Lazarus port of this Delphi package: https://sourceforge.net/projects/delphiasiovst/
Title: Re: Interfaces/Polymorphism
Post by: syntonica on December 06, 2019, 11:47:39 am
Carbon just worked, and was usable as fundament for long term libraries and frameworks. Even Adobe postponed the migration several times ( and eventually went with a cloud version)

p.s. the cloud thing is a joke, I don't think that is related to cocoa.
More true than you think. Adobe were probably still sore about having to move from 68k to PPC!  Plus, the whole "Apple killed my Flash Player!" thing probably didn't help much.

I did poke around in the LCL, but it doesn't have what I need. My GUI is fully drawn with my own widgets and interface. I need to open a window, draw on it and catch mouse and keyboard action and that's about it. My Windows and Cocoa classes are only about 250 lines each, so should be quick work to translate over, although I'm going to do the full package rather than the "only what I need" version that I have now. All of the 2D drawing packages I've seen either rely on Carbon (extinct about now) or OpenGL (gently being shoved out the door by Metal as we speak.). What most people don't realize is that Cocoa and GDI are very highly optimized by their OSes and are extremely fast. I just removed all my GUI drawing optimizations as they were slowing things down compared to just redrawing the whole window everything. I don't see either APIs going anywhere anytime soon.  I was working on an OpenGL version of my GUI and when I got it running, it wasn't any faster since I still had to do the drawing in the cpu! (NanoVG, if memory serves.)
Title: Re: Interfaces/Polymorphism
Post by: syntonica on December 06, 2019, 11:48:11 am
My first project will be porting over my VST plugin from C++ for both Mac and Windows
There is pl_AsioVST package which you can install via OPM which can help you to create VST plugins or ASIO applications. There are many included built in filters to built effects without much DSP knowledge. I am not quite sure, but I think it's only for Windows. It's a Lazarus port of this Delphi package: https://sourceforge.net/projects/delphiasiovst/
Thanks! I'll check it out!
Title: Re: Interfaces/Polymorphism
Post by: marcov on December 06, 2019, 12:26:26 pm
Carbon just worked, and was usable as fundament for long term libraries and frameworks. Even Adobe postponed the migration several times ( and eventually went with a cloud version)
More true than you think. Adobe were probably still sore about having to move from 68k to PPC!  Plus, the whole "Apple killed my Flash Player!" thing probably didn't help much.

I'm more talking about the 2003-2010 era, and then specially the (somewhat sure) rumour that there was a 64-bit Carbon but only for Adobe, not for users.

Quote
I did poke around in the LCL, but it doesn't have what I need. My GUI is fully drawn with my own widgets and interface. I need to open a window, draw on it and catch mouse and keyboard action and that's about it. My Windows and Cocoa classes are only about 250 lines each, so should be quick work to translate over, although I'm going to do the full package rather than the "only what I need" version that I have now.

If it is that small, I'd not bother with LCL either.

Quote
All of the 2D drawing packages I've seen either rely on Carbon (extinct about now) or OpenGL (gently being shoved out the door by Metal as we speak.). What most people don't realize is that Cocoa and GDI are very highly optimized by their OSes and are extremely fast.

Since Vista the drawing speeds of various operations change with GDI, and since the desktop became compositing, doublebuffering is often less needed.
However extremely fast is IMHO too much honor. I don't know COCOA, Metal and its progression good enough to judge performance.

I used Apple's for private work as *nix workstations up to 2005 partially because OS X was one of the first systems that got hibernation right, then with another architecture change and constant API breakage I gave up. And I'm glad I did when I see what followed. If app binaries can't be used for extended periods of time, for me there was little added value to e.g. BSD or Linux, which have the same problem. And Windows got hibernation reasonably right.

Quote
I just removed all my GUI drawing optimizations as they were slowing things down compared to just redrawing the whole window everything. I don't see either APIs going anywhere anytime soon.  I was working on an OpenGL version of my GUI and when I got it running, it wasn't any faster since I still had to do the drawing in the cpu! (NanoVG, if memory serves.)

Opengl is an art. Exact performance is card (+driver) dependent. But probably for normal windowing operations and control it doesn't matter.

I use opengl at work for "live" images of a vision system, and it is very fast specially on Intel APUs of generation 4000 and later (because GPU upload is suddenly magnitudes faster than with older or PCIexpress cards). Uploading, drawing (scaled) large images (e.g. 28MB)  and drawing 130.000 objects on top in the 0.1-1ms total range. 
Title: Re: Interfaces/Polymorphism
Post by: syntonica on December 06, 2019, 06:46:25 pm

I'm more talking about the 2003-2010 era, and then specially the (somewhat sure) rumour that there was a 64-bit Carbon but only for Adobe, not for users.
I'd forgotten about that. I think Adobe really, really wanted a 64-bit version, but Steve told them it was dead and to go Cocoa. Once upon a time, I had a far better finger on Apple's pulse, being in the industry. Now all I have are fading memories...
Quote
Since Vista the drawing speeds of various operations change with GDI, and since the desktop became compositing, doublebuffering is often less needed.
However extremely fast is IMHO too much honor. I don't know COCOA, Metal and its progression good enough to judge performance.
I still have to use double-buffering, otherwise I get flickering. Now that I'm redrawing the whole thing, I could maybe drop it, but the bitblit procedure to copy the buffer is so fast, it just makes things look better at 60fps. IIRC, the Cocoa NSView is still automatically double-buffered behind the scenes.
Quote
I use opengl at work for "live" images of a vision system, and it is very fast specially on Intel APUs of generation 4000 and later (because GPU upload is suddenly magnitudes faster than with older or PCIexpress cards). Uploading, drawing (scaled) large images (e.g. 28MB)  and drawing 130.000 objects on top in the 0.1-1ms total range.
For most graphics use cases, using OpenGL is a huge speed up. But for drawing 2D lines, circles, and text, you still have to make the triangles. Lots of triangles.
Title: Re: Interfaces/Polymorphism
Post by: marcov on December 06, 2019, 07:35:55 pm
For most graphics use cases, using OpenGL is a huge speed up. But for drawing 2D lines, circles, and text, you still have to make the triangles. Lots of triangles.

Actually that is wrong,  and old school opengl thinking. You can actually calculate the triangles from your own more highlevel definitions using the geometry shader. I do that all the time because I only show one in every <x>(*) images, so I write quite dense abstract info per image, and only one in every <x> is actually going to be displayed and the expansion is fairly free using the geometry shader.

p.s. x (*) typically being 5 or even more.
Title: Re: Interfaces/Polymorphism
Post by: syntonica on December 06, 2019, 08:58:50 pm
For most graphics use cases, using OpenGL is a huge speed up. But for drawing 2D lines, circles, and text, you still have to make the triangles. Lots of triangles.

Actually that is wrong,  and old school opengl thinking. You can actually calculate the triangles from your own more highlevel definitions using the geometry shader. I do that all the time because I only show one in every <x>(*) images, so I write quite dense abstract info per image, and only one in every <x> is actually going to be displayed and the expansion is fairly free using the geometry shader.

p.s. x (*) typically being 5 or even more.
Oh, okay, I see. Somebody should tell the rest of the world, though!   ;D

Honestly, it's been a couple of years since I did the work and nothing I looked at used the shaders to do this. I was about ready to adopt the OpenGL version (since it obviate the need for me to do any Windows programming) when I found out Apple was sundowning their OpenGL support, which has always been dodgy at best.

I just wish there was one graphics standard we programmers could use and leave it up to the OSes to implement it, either offloading it to the GPU, or gracefully falling back to native where necessary. Millions of programmers would breathe a sigh of relief and maybe grow some hair back.
Title: Re: Interfaces/Polymorphism
Post by: marcov on December 06, 2019, 09:03:30 pm
Actually that is wrong,  and old school opengl thinking. You can actually calculate the triangles from your own more highlevel definitions using the geometry shader. I do that all the time because I only show one in every <x>(*) images, so I write quite dense abstract info per image, and only one in every <x> is actually going to be displayed and the expansion is fairly free using the geometry shader.

p.s. x (*) typically being 5 or even more.
Oh, okay, I see. Somebody should tell the rest of the world, though!   ;D
[/quote]

here (http://at https://forum.lazarus.freepascal.org/index.php/topic,30556.msg194484.html#msg194484) is an older unit test. Try it if you can run windows binaries somehow.

Quote
I just wish there was one graphics standard we programmers could use and leave it up to the OSes to implement it, either offloading it to the GPU, or gracefully falling back to native where necessary. Millions of programmers would breathe a sigh of relief and maybe grow some hair back.

I agree, but Apple creating yet another competing standard (https://xkcd.com/927/) with metal, doesn't help things.
Title: Re: Interfaces/Polymorphism
Post by: syntonica on December 06, 2019, 09:44:05 pm
I agree, but Apple creating yet another competing standard (https://xkcd.com/927/) with metal, doesn't help things.
No, they should have got together with Intel, NVidia and AMD, et.al., and created one together. OpenGL is fine, but getting long in the tooth with however many current versions there are...

I tried reading up on Metal and how to draw a teapot. At about step 32 in setting up the canvas, my brain exploded.  %)
Title: Re: Interfaces/Polymorphism
Post by: syntonica on December 26, 2019, 11:29:37 pm
Okay, dear Friends, it's crunch time!
First, the code:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}
  2.  
  3. type
  4.   THello = class
  5.     public
  6.       function WhoAmI: string; virtual;
  7.   end;
  8.  
  9.   TWorld = class(THello)
  10.     var
  11.       i: integer;
  12.     public
  13.       function WhoAmI: string; override;
  14.       function ANewMethod: string;
  15.   end;
  16.  
  17.   function THello.WhoAmI: string;
  18.     begin
  19.       Result := 'Hello'
  20.   end;
  21.  
  22.   function TWorld.WhoAmI: string;
  23.     begin
  24.       Result := ' World'
  25.   end;
  26.  
  27.   function TWorld.ANewMethod: string;
  28.     begin
  29.       Result := 'How are you?';
  30.   end;
  31.  
  32. var
  33.   a: THello;
  34.   b: TWorld;
  35.  
  36. begin
  37.   b := TWorld.Create;
  38.   WriteLn(b.WhoAmI);
  39.   WriteLn(b.ANewMethod);
  40.   b.i := 9;
  41.  
  42.   a := b;
  43.   WriteLn(a.WhoAmI);
  44.   WriteLn(a.ANewMethod); // <--- Fails compile!
  45.   a.i := 9;     // <--- This too!
  46. end.
  47.  
C++ happily can use a parent pointer to point to a child class and resolve its added methods and fields.  The VST framework deeply relies on this.

How can I get Pascal to do this? What am I missing?
Title: Re: Interfaces/Polymorphism
Post by: simone on December 27, 2019, 12:21:52 am
I'm not sure to understand your question. However you can compile the above code without errors using 'conditional typecasting':

Code: Pascal  [Select][+][-]
  1. ...
  2. begin
  3.   b := TWorld.Create;
  4.   WriteLn(b.WhoAmI);
  5.   WriteLn(b.ANewMethod);
  6.   b.i := 9;
  7.  
  8.   a := b;
  9.   WriteLn(a.WhoAmI);
  10.   WriteLn((a as TWorld).ANewMethod); // <---
  11.   (a as TWorld).i := 9;     // <---
  12. end.

Or using 'hard typecasting':
Code: Pascal  [Select][+][-]
  1. begin
  2.   b := TWorld.Create;
  3.   WriteLn(b.WhoAmI);
  4.   WriteLn(b.ANewMethod);
  5.   b.i due:= 9;
  6.  
  7.   a := b;
  8.   WriteLn(a.WhoAmI);
  9.   WriteLn(TWorld(a).ANewMethod); // <---
  10.   TWorld(a).i := 9;     // <---
  11. end.

I hope this can help you.
Title: Re: Interfaces/Polymorphism
Post by: howardpc on December 27, 2019, 12:25:31 am
It may be better to introduce a common ancestor class. Something like this:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. type
  6.  
  7.   TBase = Class
  8.   public
  9.     var
  10.       i: Integer;
  11.     function WhoAmI: String; virtual; abstract;
  12.   end;
  13.  
  14.   THello = class(TBase)
  15.   public
  16.     function WhoAmI: String; override;
  17.   end;
  18.  
  19.   TWorld = class(TBase)
  20.   public
  21.     function WhoAmI: String; override;
  22.     function ANewMethod: String;
  23.   end;
  24.  
  25.   function THello.WhoAmI: String;
  26.   begin
  27.     Result := 'Hello';
  28.   end;
  29.  
  30.   function TWorld.WhoAmI: String;
  31.   begin
  32.     Result := ' World';
  33.   end;
  34.  
  35.   function TWorld.ANewMethod: String;
  36.   begin
  37.     Result := 'How are you?';
  38.   end;
  39.  
  40. var
  41.   h: THello;
  42.   b: TBase;
  43. begin
  44.   h := THello.Create;
  45.   h.i := 9;
  46.   WriteLn(h.WhoAmI,' h.i=',h.i);
  47.  
  48.   b := h;
  49.   WriteLn(b.WhoAmI,' b.i=',b.i);
  50.   b.Free;
  51.  
  52.   b := TWorld.Create;
  53.   b.i := 99;
  54.   WriteLn((b as TWorld).WhoAmI,' b.i=',b.i);
  55.   WriteLn((b as TWorld).ANewMethod);
  56.   b.Free;
  57. end.
Title: Re: Interfaces/Polymorphism
Post by: simone on December 27, 2019, 12:30:35 am
My solution is 'quick and dirty'. The proposal of Howard is conceptually more correct.
Title: Re: Interfaces/Polymorphism
Post by: syntonica on December 27, 2019, 01:06:39 am
I'm not sure to understand your question. However you can compile the above code without errors using 'conditional typecasting':

I hope this can help you.
It confirms that I had the right idea, but still the VST framework is passing around the wrong pointers. Overridden methods work fine, but additional fields and methods are not found whatsoever, even with casting.


I know it can be done, so I'll have to study the code some more.
Title: Re: Interfaces/Polymorphism
Post by: syntonica on December 27, 2019, 01:12:40 am
It may be better to introduce a common ancestor class. Something like this:
That might be the solution I'm looking for, except that I cannot inject variables into my base class.  :(

I'd do my class as a helper instead, but I have a couple dozen fields that I cannot include, but are required for the additional methods.
Title: Re: Interfaces/Polymorphism
Post by: simone on December 27, 2019, 07:00:50 am
It may be helpful to provide a portion of C ++ code to better illustrate your problem.  In this forum there are many who are fluent in this language too.
Title: Re: Interfaces/Polymorphism
Post by: simone on December 27, 2019, 10:40:15 am
You can try using the composition instead of inheritance. Or try using some design patterns. In the absence of more specific information, I cannot give you more concrete suggestions.
Title: Re: Interfaces/Polymorphism
Post by: syntonica on December 27, 2019, 11:10:02 am
You can try using the composition instead of inheritance. Or try using some design patterns. In the absence of more specific information, I cannot give you more concrete suggestions.
Thanks! That's okay. It would take more than one reply to try to explain how the VST framework works. It's not pretty, even on a good day. At its core, it's plain C with structs, but with a C++ overlay that adds a number of function pointers and opcodes and that all communicates back and forth with a host. I'm still sorting it all out...

I've noticed that I'm running into issues with automatic coercion, so that's my next project. For Ints vs Singles, it's far, far better than the C++ experience in that it works as expected. My C-code is littered with casts that should be unnecessary.  However, with pointers... ugh... That might be where my issue lies. Maybe. I'm still trying to figure out how one LFO is modulating TWO parameters...  %)
Title: Re: Interfaces/Polymorphism
Post by: syntonica on December 28, 2019, 02:20:00 am
I'm still trying to figure out how one LFO is modulating TWO parameters...
Duplicating a bug in the original code (missing break statement) takes talent!  :D

Looking at all the weird issues I've been seeing with junk values and missing members all seem to be pointing to one thing. Somehow, my plugin instance or managed members are being refcounted to zero and disposed of.  It would explain why a pointer is fine one line but completely invalid with a different value 10 lines later. The only thing I can do is create an instance of my plugin class and hand it off to the host.

Is there a way to turn refcounting off?  I already manage my memory in both C++ and Obj-C and 95% of what I create needs to be persistent for the lifetime of the plugin and is already set to be released in the destructor methods.
Title: Re: Interfaces/Polymorphism
Post by: syntonica on December 28, 2019, 02:27:36 am
This is the code that is exposed to the host to instantiate a plugin (error checking removed for clarity):
Code: Pascal  [Select][+][-]
  1. function VSTPluginMain(audioMaster: TAudioMasterCallbackFunc): PAEffect; cdecl; export;
  2.   begin
  3.     {error check}
  4.     eff := MyEffect.Create(audioMaster);
  5.     {error check}
  6.     Result := eff.Effect;
  7.   end;
  8.  
PAEffect is a pointer to a record containing a reference to the created plugin.
TinyPortal © 2005-2018