COM Importer for Island

The Oxidizer doesn’t seem to work well for converting COM types?

For example, I have the following Delphi interface (as imported using Delphi’s typelib importer)

_IVehicleEvents = interface(IUnknown)
    ['{266A8735-597B-45BD-90CB-80796741BD64}']
    function Departure(idVehicle: Integer; dTime: Double): HResult; stdcall;    
  end;

The conversion seems a total mess:

  _IVehicleEvents := &interface(IUnknown)[];
  Departure(idVehicle);
  HResult;
  stdcall;
  &end;

Thanks, logged as bugs://82751

Meantime, does Fritz’s tool handle the better/help here, perhaps? Some Helper Tools for Migrating Delphi Projects to Elements

I have added a Small Tool SimpleConvert.sln
Should do the work

3 Likes

nice!

Thank you @FritzW!!! It converts. I am now checking it but it appears in good shape!

1 Like

Nice to here,
if there are some problems, come on with it, I’m happy to help

@FritzW Thank you.

The converted file cannot compile, which is fine and expected. It seems to have the following problems? I guees a manual tune-up is in order.

  • TGUID (Delphi) -> TGUID directly, not recognized by Island
  • TOleEnum (Delphi) -> TOleEnum directly, not recognized by Island.

Delphi record is converted to Island Record, with all the fields by reference, which doesn’t seem right:
Delphi:

  STsmTransitInfo = record
    nSize: Smallint;
    id: Smallint;
    nPassengers: Smallint;
    nMaxCapacity: Smallint;
    idRoute: Integer;
    idStop: Integer;
    fDelay: Single;
    lReserved: Integer;
  end;

Island Converted:

  STsmTransitInfo = public record
    var nSize: Int16;
    var id: Int16;
    var nPassengers: Int16;
    var nMaxCapacity: Int16;
    var idRoute: Integer;
    var idStop: Integer;
    var fDelay: Single;
    var lReserved: Integer;
  end;
  • Delphi calling convention safecall is converted to safecall. Should it be Stdcall?

Do you think I could send you a copy of the original typelib.pas, and the converted one, for a quick review? Many thanks.

what’s the problem here, the record looks correct to me?

Note that the converter, like Oxidixer, will adjust the language for you, it will not translate the APIs. To the converter, TGUID is just “some type” it knows nothing about, just like TMyFancyButton would be. It doesn’t know if there’s an equivalent in core Elements, Elements RTL, or the target platform.

In this case, we do have a Guid type both in Island RTL and — cross-platform — in Elements RTL that you can use instead of TGUID. TOleEnum I have of course no idea what it is.

No, safecall and stdcall are vewry different things. I’m not sure of we support safe call yet (@ck?). Essentially, safecall is a special calling convention intended by Delphi (iirc) that wraps exception handling, under the hood, a different method signature is used and the method returns an HResult that indicates the exception, and passes the exception via some special means (again, iirc).

You will probably need to use the “lower-level” actual calling convention and method signature (at least for now).

Check out https://stackoverflow.com/questions/96042/whats-safecall.

Oh Sorry. Yes they are correct and actually the same. I got confused when I saw var

Understand. safecall is actually the same as stdcall , except Delphi adds some additional compiler magic when it comes to HRESULT handling (probably some exception handling too as I recall). But I feel it is a little tricky here for the conversion. Hence I raised it up.

Probably the most neatest way is still a direct COM importer that deals with the type library directly, rather than this in-direct converting (i.e., converts from a Delphi imported type library file).

I just found TOleEnum = type LongWord

Also I realized that when I import the COM library using Delphi, I should do a RAW importing - that would get rid of safecall, which is really a delphi specific thing.

Let me continue to do the manual tune-up, and see.

OK. I think I am almost there.

  1. I use Delphi’s tlbimp.exe tool, which is under Delphi’s bin64 folder, to do a RAW import, using command line switches to generate a RAW import file, WITHOUT generating safecall:
    tlbimp.exe COMLib.exe -P -Ps- -O-
  2. In the Delphi generated file, I removed all dispinterface, which as I understand, is not supported by Island (yet)
  3. Do a quick find/replace, change TOleEnum to LongWord
  4. Do a quick find/replace, change WideString to OleString
  5. Do a quick find/replace, change OleVariant to VARIANT
  6. Use @FritzW SimpleConvert tool, generated the converted file

Now it is in much better shape, and Island compiler only complains the following thing::

const LIBID_TsmApi: GUID = '{1DA9E83D-B7FF-49D2-B3FC-49AE2CEE10F7}';  // Type mismatch, cannot assign "String" to "rtl.GUID"

So I guess I have two questions @mh :

  • Should I use Island VARIANT for the COM’s VARIANT?
  • How to declare a GUID constant?

Fwiw, you might easier just declare these as aliases.

Yeah, a Guid is a class, and can’t be a constant. What you’ll wanna do is declare the string as a constant, and the create the Guid from it as needed, ie:

const LIBID_TsmApi = '{1DA9E83D-B7FF-49D2-B3FC-49AE2CEE10F7}'; 

// ... elsewhere

... := new Guid(LIBID_TsmApi);

Not sure on the whether we support Variants in Island at all, but chances are kid the type is define din Island RTL we probably do. Better check with @ck tomorrow (or just try it ;).

Update: I don’t see Variant in Island RTL, so I don’t believe we support them for now.

@mh

En… now I have the compiler crashed:
------ Rebuild All started: Project: TsmPluginCore, Configuration: Release ------
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\RemObjects Software\Elements\RemObjects.Elements.Island.Windows.targets(70,3): error E0: Internal error: System.IndexOutOfRangeException: Index was outside the bounds of the array.
at RemObjects.Oxygene.Code.Classes.MyDictionary1.set_Item(String key, TValue value) at RemObjects.Oxygene.Code.Compiler.Compiler.PatchInterfaceCom(IMutableParsedType bpt) at RemObjects.Oxygene.Code.Compiler.CheckMembersVisitor.VisitType(IParsedType aType) at RemObjects.Oxygene.Code.Compiler.Compiler.ForAllInternalTypes(Action1 aAt)
at RemObjects.Oxygene.Code.Compiler.Compiler.CheckMembers()
at RemObjects.Oxygene.Code.Compiler.Compiler.Compile()
Done building project “TsmPluginCore.elements” – FAILED.

We’ll need a test case.

@mh Just sent to your email, please kindly check.

1 Like

Reproduced, thanx!

Thanks, logged as bugs://82755

bugs://82755 got closed with status fixed.

@ck.
Island VARIANT is COM VARIANT’s counterpart?