Find some minimal COM creating examples

Hi friends, recently i learn some basic to create COM in c language, it is fun. then i tried to use the knowledge to do the same thing in Island platform, but i don’t get clear clues how to get started, because the language and platform seem like encapsulated some details,i’m not sure how to deal with, can you please provide some minimal examples to show how to create COM in Island? comprehensive examples are nice but not necessary, thanks

For developing in-process COM (Dll) using Island, you would have to export those standard COM DLL exported functions so you can register it with system registry. Or, for registry-free COM Dll, you can just export customized COM class factory returning the IUnknown interface to the caller.

Bottom line - You have to do some heavy lifting yourself, if you want to use Island to develop standard COM components.

If you want to consume external COM components from Island application, the best way is to use Delphi import the type library and convert it to Oxygene.

If you have used C to develop COM components, then you can just treat Island/Oxygene basically the same since all the system COM APIs (ole.dll) are the same.

1 Like

@wuping, thank you for your hints, i studied the IslandRTL source code files: interfaces.pas and IDispatch.pas. suddently understood some magic behind, as you said, basically there are same at APIs, it is still primity like using c to implement. need some homework to make it works.

I did ActiveX dll and exe using VB6 - a long time ago.
Point with that is that VB did everything for me; I wasn’t bothered with how it worked.
Meaning that I do not know anything about it.

So if you figured it out, can you share some templates or examples so that I have a start point for this?

I’ll try to get someone form the team to out together notes so I can create a doc topic for this, next week. Unfortunately it’s out of my own wheelhouse of expertise; the last time I dealt with COM directly was with Delphi 3. :joy:

If you have Hydra, it uses COM extensively under the hood, so the Island plugin sources might Gove some good examples.

1 Like

Hi Theo, i’m afraid can’t give you some useful examples recently. there files i mentioned about merely define the IUnknown and IDispatch’s vtable records that can be useful for futher development. however i simply gave up to develop COM server in Island right now. in order to make the COM server useful without framework support, you still need to manually make many trivial jobs like defining interfaces, implementing the interfaces, creating the class factories, making IDL definitions, defining dll entries and so on… . that’s time comsuming compare to other approach. i just made a COM server for sending/receiving hardware serial data using .Net framework within 1 hours so easily. finally calling its functions in PHP scripts, everything works soon and fine.

I assume y’all have seen https://docs.elementscompiler.com/Compiler/BackEnds/Island/COM/, right?

Island/Windows COM programming, involves two subjects: 1) consume external COM components in Island 2) Develop COM components for external ( non-Island )client

Re: Subject 1 involves importing the type library of the external COM components (for both in-process dll-based COM and out-process automation server). This essentially is a process of generating interface definitions for an Island language (e.g. Oxygene). Unfortunately, there is no type library importer (yet) for the Island platform - this means, the best/practical way is to use Delphi type library importer to generate the import in Delphi then edit it to Oxygene syntax. Note: after convert the import from Delphi to Oxygene, you can use/mix the Oxygene file with other RemObjects languages such as C#, so you don’t really need to do the import for other languages

Re: Subject 2
To develop COM components in Island languages to be consumed by external non-Island clients, is much trickier.

Ideally this requires the Island compiler to generate a type library (and embedded the typelib in the Dll or Exe as resource), but this is not available (yet)

So from the Client side (like .NET C#, C++, FORTRAN, Delphi) to consume a DLL-bass COM developed in Island, you must first manually define customized class factories on the Island side, then call those customized class factories from the Client side. The simplest form of a customized class factory is just return an IUnknown ptr to the caller. This is actually the “Registry Free” fashion that I prefer.

The above is about developing Dll-baaed COM with Island.

For Exe-bass COM automation server, I am not very sure that Island compiler can generate the COM-compatible Exe - I have not investigated that yet. But it would be good to be confirmed by RemObjects development team.

—— overall, there will be a lot heavy lifting but it is definitely doable and acceptable (for me) especially the detour using Delphi . I guess this is understandable. Island is a fairly new platform. The similar LLVM-based Rust language doesn’t have matured COM support either, so I don’t blame Island for that!

—- maybe the community can work out a type library importer for Island (or RemObjects team)? It is not a complicate process. Windows already provides type library APIs (win32 and .NET) to parse the types as defined in type libraries after all. All that is needed is to translate the parsed types to the syntax of an Island language.

I did now - but I miss the information about in-process (dll) and out-of-process (exe), threading types, register component and indeed as wuping said, the TLB files

All we support, at this stage, is compiler/language-level interaction with COM interface references, and implementing COM interfaces own classes.

It’s up to you to use Win32 APIs (or whatever else that might give you COM interfaces back, eg CoCreateInstance) to obtain the interfaces you wanna work with, or to expose your own — just as you would in, say, C or other Win32-API-level code.

The one thing I do see as “missing” (as in, would be a nice feature request) is TLB import. to generate interface code; this is logged as bugs://76848: Create TLB importer for Island.

marc, first step, i just realize how can we write an island dll ? there are no templates no sample codes in Water

1 Like

Just create a new Library project and change its OutputType from StaticLibrary to Library.

In addition to that, you would also need to declare exported functions, something like below (and see attached sample file).DllExports.pas (839 Bytes)

Note:

  • The exported symbol name can be different from the actual function name, in the example below, we have the function name “Add”, but we export the function in a different name “Sum”.

  • The DllMain must have the following attribute:
    [SymbolName(’__elements_dll_main’, ReferenceFromMain := true)]


namespace  DllExports

    uses
      rtl;

      [SymbolName('Sum'), DLLExport, CallingConvention(CallingConvention.Stdcall)]
      method Add(a: Int32; b: Int32);
      begin
        result := a + b
      end;

      {/*! Dll entry point. */}
      [SymbolName('__elements_dll_main', ReferenceFromMain := true)]
      method DllMain(aModule: HMODULE; aReason: DWORD; aReserved: ^Void): Boolean;
      begin
        method GetPluginDllPath: String;
        begin
          var lBuffer: array of Char := new Char[MAX_PATH];
          GetModuleFileName(aModule, lBuffer, MAX_PATH);
          exit String.FromCharArray(lBuffer);
        end;

        case aReason of
          DLL_PROCESS_ATTACH:
    	    exit true;
          DLL_PROCESS_DETACH:
            exit true;      
          DLL_THREAD_ATTACH:
            exit true;      
          DLL_THREAD_DETACH:
            exit true;
        end;
      end;

    end.

Well, “need” is a strong word, it depends on what you’re doing with the .dll. If you want to make C-level functions available to the non-Island callers, then you need to export those functions, yes :wink:

marc - do you mean - to use the Dll with Island callers (of different project), there is no need to export symbols?

I guess (?) not only ordinary “C-level functions” - actually we can also export Island COM interface to C++ or Delphi callers directly. The export function can also take C++ abstract class pointers or Delphi interface; both have v-tables that are ABI compabitle with Island COM interface. These are good features enabling Island to generate “Registry Free” COM component, though.

Hmm, good q. id expect that just with a static library, all public methods and types should be available to Island, when referent ing the .fx.

Right, but technically you’re not exporting the class/interface, you’re exporting some method that returns the COM interface pointer.

I was once as confused as @865147540. So I guess to help him get started, it is better to clarify:

  • To make a C-compatible Dll, we do need to export symbols, as noted above. We can also transfer Island COM interface via Dll to C++, Delphi, or any native callers that speak COM.

  • Additionally, Island can also generate “static library” (similar to C static lib, but in Island’s own meta data format) with .fx suffix for Island’s own cross-language/platform interoperability. Island static lib (.fx) is neither COFF nor OMF format like typical C static libs.

Please correct if anything is wrong in the above statement.

Correct, but you can have the compiler emit a .h file for your static library and sue that from C/C++/Objective-C or anything else that can deal with .h files. There’s a project setting to turn that on.

I am scratching my head - what project setting to enable generating .h file for Island static library(.fx)?

hi folks, i made a mini example, please check it out. thanks to wuping, i learn how to make DLL by his code. and mh

Mini COM Demo in Island

This COM demo still in experimental stage, not a working example! however it shows
some idea and basic skeleton behind.COM-Demo.7z (5.3 KB)

still some strange issues, following code will show undefined symbol error:
InterlockedIncrement( &GlobalVariables.ServerLockCount );
InterlockedDecrement( &GlobalVariables.ServerLockCount );

3 Likes