2

I'm currently trying to reimplement a com interface. This interface is currently used in a Delphi project. The Delphi interface code is presumably machine generated using "TLIBIMP.EXE -P") In this autogenerated code there is for example this interface:

IDPets = interface(IDispatch)
    ['{679DDC30-232F-11D3-B461-00A024BEC59F}']
    function Get_Value(Index: Integer): Double; safecall;
    procedure Set_Value(Index: Integer; Value: Double); safecall;
    function Get_Pet(Index: Integer): IDPets; safecall;
    procedure Set_Pet(Index: Integer; const Ptn: IDPets); safecall; 
    property Value[Index: Integer]: Double read Get_Value write Set_Value;
    property Pet[Index: Integer]: IDPets read Get_Pet write Set_Pet;
end;

As you can see there are multiple property which are accessed like fields or arrays using square brackets.

What did I have achieved so far:

In C# it's possible to write one indexer accessor using this code

[System.Runtime.CompilerServices.IndexerName("Cat")]
public ICat this[int index] { get; set; }

(from: How do I export an interface written in C# to achieve Delphi code generated by TLB)

The question:

But now I need to have more than one indexer in a class. And they only differ in their return type so I can't simply overload the "this" keyword.

So does anyone have an idea how I can implement this in C# so that I get an TLB file which than can be used to generate the Delphi code you can see in the top of this post?

Any ideas are highly appreciated.

Edit: I already stumbled across this post https://stackoverflow.com/a/4730299/3861861 It kind of work, So I'm able to export multiple properties with an index to Delphi. But the type of this properties are not the right one. For example: a double is not a double it is an IIndexerDouble (I needed to remove the generic from the indexer for the com export, so I had to write an indexer for every datatype I want to use)

White
  • 157
  • 9

1 Answers1

1

You don't need to "have more than one indexer in a class". What you really need is to have several indexed properties in Delphi.

Let's say you want to add the Dog indexed property. Start by adding these regular methods to the C# class:

public Dog GetDog(int index)
{
    ...
}

public void SetDog(int index, Dog value)
{
    ...
}

They will generate this:

function GetDog(Index: Integer): IDDogs; safecall;
procedure SetDog(Index: Integer; const Ptn: IDDogs); safecall; 

Now just add the declaration for the indexed property:

property Dog[Index: Integer]: IDDogs read GetDog write SetDog;
Olivier
  • 13,283
  • 1
  • 8
  • 24
  • That is a way which is possible to do. But that requires more manual steps to do on every iteration of the interface. I''m looking for a solution where I don't need to manipulate the .pas file after it is generated by tlbimp.exe. The original code pas file looks like it is also completely automated generated with no manual intervention. – White Apr 23 '20 at 12:32
  • The original COM component was not written in C#. You could try naming the methods `get_Dog()` and `set_Dog()`, and, if you're lucky, tlibimp.exe will interpret them as an indexed property. If it doesn't, then you have no solution (other than manual editing). – Olivier Apr 23 '20 at 12:55
  • This sadly doesn't work so I think there is no other solution than patching the .pas file after it is generated. I also tried this solution: https://stackoverflow.com/a/23081403/3861861 But it does not work either. The first interface which the class implements get the [default] tag in the TLB file. And tlbimp.exe ignores the second interface completely. – White Apr 23 '20 at 15:02
  • Ok I now wrote a Patcher application. It parsed the pas File and generate properties for matching setter and getter functions and so on. Thanks for your help. – White May 11 '20 at 15:48