Find some minimal COM creating examples

Nice!

mind if I use this as the basis for a “COM dll” template"?

1 Like

never mind, i would be happier to help others. it compiled successful but just not working, need your help. i would like to make an example implemented IDispatch that used tlb too, but need this example works first as basis. this is not like C, you can handle every detail without guess

it shows error code in hr: -2147221164, maybe it’s “class not registered” message
-2147221164 is COM error code E_NOINTERFACE, which means the following GUID comparing code of yours is not right:

public rtl.HRESULT QueryInterface(rtl.GUID* riid, void** ppvObject)
		{
			rtl.HRESULT rc = E_NOINTERFACE;
			if( ((RemObjects.Elements.System.Guid*)riid)->Equals( rtl.IID_IUnknown )){
				*ppvObject = (IEvalStr*)(&this);
				rc = S_OK;
			}
			else if( ((RemObjects.Elements.System.Guid*)riid)->Equals( guidOf( IEvalStr ) ) ){
				*ppvObject = (IEvalStr*)(&this);
				rc = S_OK;
			}
			return rc;
		}

If you look into Island RTL source code, you can see that RemObjects.Elements.System.Guid.Equals really compares the reference, NOT the value! Looks like you should use the Equal operator instead of Equals() method:

RemObjects.Elements.System.Guid.Equal(*riid,  IID_IUnknown)

Alternatively, you can just do a memcmp(riid, &IID_IUnknown, sizeof(rtl.GUID), or directly compare GUID string like (*riid).ToString() == IID_IUnknown.ToString()

But my question is: why bother? There is a lot of boilerplate work that needs to be done if you would like to establish a COM framework for Island. Seems to me it makes more sense just do “Registry Free” COM with Island, i.e., just returning a COM pointer from a specialized DLL exported function.

thank you for pointing those errors out. i fixed it, still not working, the entire dll not get called at all. technically if you would like to do Registry Free COM. the dll itself don’t need to change, but you need to implemente a custom CoCreateInstance(… ) to skip registry operations, some symbolic code like this

MyCreateInstance(){
  LoadLibrary( "MyCom.dll" ) 
  GetClassObject = GetProcessAddr( "DllGetClassObject" )
  factory = GetClassObject( clsid, IID_IClassFactory, ppv )
  icom = factory.CreateInstance( clsid, iid );
  icom.AddRef()
  FreeLibrary()
  return icom // your com interface
}

Hmm, that sounds like a bug? will fix.

Hm, this looks good to me?

    method &Equals(obj: Object): Boolean; override;
    begin
      if assigned(obj) and (obj is Guid) then
        exit self = Guid(obj)
      else
        exit False;
    end;

    class operator Equal(Value1, Value2: Guid): Boolean;
    begin
      exit (Value1.Data1 = Value2.Data1) and
           (Value1.Data2 = Value2.Data2) and
           (Value1.Data3 = Value2.Data3) and
           (Value1.Data4_0 = Value2.Data4_0) and
           (Value1.Data4_1 = Value2.Data4_1) and
           (Value1.Data4_2 = Value2.Data4_2) and
           (Value1.Data4_3 = Value2.Data4_3) and
           (Value1.Data4_4 = Value2.Data4_4) and
           (Value1.Data4_5 = Value2.Data4_5) and
           (Value1.Data4_6 = Value2.Data4_6) and
           (Value1.Data4_7 = Value2.Data4_7);
    end;

Marc - it appears to me that the code of Equals () compares reference of the subject GUID to the second GUID. This doesn’t seem to be a bug but rather a design?

If we want to compare two GUID by value, it appears to me we should use Equal (a,b)

But there’s class operator Equal(Value1, Value2: Guid): Boolean; so exit self = Guid(obj) should hit that, no?

Hi marc - thank you for your attention. But it doesn’t seem to work like that. Testing code below:

namespace ConsoleApplication;


type
  Program = class
  public

    class method Main(args: array of String): Int32;
    begin
      var guid1 := rtl.IID_IUnknown;
      var guid2 := new RemObjects.Elements.System.Guid('{00000000-0000-0000-C000-000000000046}');

      if guid1 = guid2 then  // This will be hit
        writeLn('RemObjects.Elements.System.Guid.Equal operator () works');

      if guid2.Equals(guid1) then  // This will NOT!!!!! be hit
        writeLn('RemObjects.Elements.System.Guid.Equals () works');
    end;

  end;

end.

ConsoleApplication.zip (2.0 KB)

Thanks, logged as bugs://84573

bugs://84573 got closed with status fixed.

Ah! this is because rtl.GUID vs Guid are two distinct types. I’ve added an extra check to the equals method to support this.

2 Likes