Is Oxygene Island ABI with C struct, or C++ pure abstarct class v-table?

Is Oxygene/Island Interface ABI compatible with C/C++ pure-abstract class V-table?

I want to pass a pointer of C struct to an Oxygene/Island as an Interface reference, and use Island Interface reference to invoke the method of that C Struct?

This trick works with Delphi. Is it going to work with Island?

I think there is a better trick. You can directly pass COM interfaces between Island and Delphi.
But there is a bug in the current build of Elements. I’m waiting for the next build to fix it.
In this build you can pass the interface from Delphi to Island, and call its methods, but cannot instantiate an object in Island implementing that interface and pass it to Delphi(this is a bug, it was working before).

I understand, but that is not what I intend to do. I want to inter-op a C++ pure abstract class or a C struct with Island. Hence I am asking if C/C++ V-Table is ABI compatible with Island’s interface reference. I knew Delphi interface reference is ABI compatible with C/C+ virtual table.

Sorry, I got it backwards. I thought you wanted Island-Delphi interop. You can declare an interface in Island as

[COM, Guid("......")] 
ITest = public interface
....
end;

And it should be compatible with the code you currently use.

The situation in elements is a little trickier. We have several class models. Island, cocoa, com.

The default is island and in island mode, the classes have a vmt at 0, then the data of the root class, and sub classes. Island interfaces act like regular class references (the pointer is exactly the same) but they do some magic vmt calls to invoke the right interface method. So no these are not like c++ abstract classes. Com interfaces are (with the requirement that they are based on iunknown). These are interfaces with the [com] attribute. (Besides the bug Jose is talking about ofc)

ck, jose, thank you for your prompt response.

Probably I wasn’t clear in what I am looking for -

I have a C++ application (which is NOT in my control) running on MS Windows - that C++ host application anticipates a call-back data structure like below:

struct IFooBarInterface
{
public:
virtual void OnSuccess(double aTime) = 0;

virtual bool OnFail(const BSTR msg) = 0;
};

I would like to use Oxygene/Island to return an ABI-compatible Oxygene class (or interface, or record).
Probably returning a pointer to the C++ host, and the C++ host will cast it into IFooBarInterface in C++.

Will this work?

Thanks again.

A struct will work. Interfaces won’t since above isn’t iunknown alike.

1 Like

So on Island side, I should use a Struct(record) too?

Another question - in Island, how can I specific Alignment? For example 8 byte alignment of record type.

We don’t currently do numeric alignment. We do ‘abi alignment’ or packed. What do you need align 8 for?

The 8 alignment is needed because the C++ host expects so.

The methods of the C++ pure abstract class (which is conveniently declared as a pure abstract struct, though) - may have data struct as parameter. And those data structs need to be 8 aligned.

For example,

C++ side

   // A C++ data struct. 
   #pragma pack(push, 8) // 8-byte packing
   struct Data {
         double Field1;
         int Field2;
         int Field3;
    }
   #pragma pack(pop)
    // A C++ pure abstract class, all methods virtual. 
    struct IMyCplusplusDataInterface { 
         virtual int FooBar(Data* aData) = 0;
    }

On Island side, I would need to create a mapping Oxygene class instance for IMyCPlusplusDataInterface and return that instance back to the C++ host. The C++ host will use that Island-returned instance to call back later. The mapped Oxygene class should be something like:

TMyOxygeneDataInterface = public class  
    method FooBar: Integer; virtual ; abstract;
end;

Questions:

  • Is this possible with Island? On Island side, is the matching pure abstract Oxygene class ABI compatible with the C++ pure abstract class (which is declared as a struct, though)?

  • Further, the C++ host also expects fastcall as calling convention. Does Island fully support fastcall on 32 bit ( I knew 64 bit calling convention is just one for all)?

So in this particular case, the alignment of the 3rd field will be off. doubles are 8 byte aligned, ints 4 byte (so you’d need padding on Field3 to allign that on 8 bytes). I’ll log a research issue to fix this though.

struct IMyCplusplusDataInterface { 
         virtual int FooBar(Data* aData) = 0;
    }

This would have to be something like:

FooBarType = function(aData: ^Data): Integer;
IMyCplusplusDataInterface = public record 
         FooBar: FooBarType;
end;

That’s a good question… I haven’t tested fastcall at all. We have it in the CallingConvention enum, but I’ve never tried it.

Yes! Please. I will test it for you whenever it is ready. I cannot wait.

Thanks, logged as bugs://82707

For that alignment issue, hopefully we can have a solution/fix soon. That is really needed urgently for me to proceed with my time-critical experimental project of Island. We have a publication submission deadline really soon.

Another really desired feature is the COM type library importer for Island. Hope we could have it soon.

Many thanks - CK. And I want to tell you that I like Island/Oxygene

The Alignment issue is easier to do than the TLB importer (as that’s a whole new thing); though I still need to import both. Is this a well known library’s TLB you want to import or a custom one? Is it big?

What about to teach Oxidizer to translate Delphi COM interfaces ITest = interface […GUIDString…] to [COM,Guid(…)] ITest = public interface ?

1 Like

The type lib is a proprietary type lib. Not very big. The type lib importer I can wait, or I can use Delphi do the importing then use Oxygene converter?

The alignment support I really need it soon so I can start running my traffic simulation experiments asap :slight_smile: . I have experimented with Island and developed a cool traffic network simulation package and I am satisfied with its computational performance against C/C++; but I am held back by this alignment issue. Your help and support is greatly appreciated. Also in the academic publication we are going to submit we will surely give credits and exposure to Island !

Note that worst case, you can adding dummy fields to get 8 byte alignment right:

type 
  [Packed]
  ABC = public record
     Field1: Double; // 0
     Field2: Integer; // 8
    Dummy1: Integer; // filler
    Field3: Integer; // 16
  end;

Obviously, not a final solution, but it works for now.

The C++ Struct method will have an implicit “this” pointer as the first argument (when the calling convention is fastcall in Win64)

So on Island side, I suspect it will not work by using the record way advised. Would the “this” pointer be any issue?

Ah right sorry; I should have said:

FooBarType = function(aSelf: ^IMyCplusplusDataInterface; aData: ^Data): Integer;
IMyCplusplusDataInterface = public record 
         FooBar: FooBarType;
end;