Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2023-11

IDispatch with Variant is not working on Linux. Why?

4 messages · 2 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Anthony Walter

Is there any reason why the late binding of properties and methods through of IDispatch interface with the Variant type is not working on Linux?

I am writing a cross platform embeddable JavaScript toolkit for Free Pascal. I wanted to use IDispatch with variants so that the experience with be more fluid for eventual end users. My goal of was to allow code like this to run:

var
  Script: IScript;
  V: Variant;
begin
  Script := NewScript('let person = {"name":  "James", age: 24}; let speak
= () => log(person.name)')
  V := Script.This;
  V.person.name = 'Ralph';
  V.speak(); // writes out Ralph
  V := V.person;
  WriteLn(V.age); // write out 24
  V.address.street := '123 Skippy Lane'; // add address object with a
street to person
  WriteLn(V.state); // writes out Undefined
end;

In the above code Script.This is a property returning an IDispatch interface holding an internal reference to the top level script object. The problem I am having with my current trunk version of fpc is that when I use a Variant that is assigned an IDispatch, no IDispatch methods to lookup and things like "person", "name", or "age" are ever evaluated.

Instead I get this:

Project dispatcher raised exception class 'External: SIGSEGV'.

Here is an example program. Not one WriteLn() in the example ever executes. Instead at runtime when V.Hello is evaluated I get the above exception. I believe fpc does support late time binding of IDispatch even on Linux as no inherent tie to Microsoft Windows functions are needed to make use of the IDispatch interface. So what is going on?

program Dispatcher;
{$mode delphi}
type
  TDispatcher = class(TInterfacedObject, IDispatch)
  public
    function GetTypeInfoCount(out Count: LongInt): HResult; stdcall;
    function GetTypeInfo(Index, LocaleID: LongInt; out TypeInfo): HResult;
stdcall;
    function GetIDsOfNames(const IID: TGUID; Names: Pointer;
      NameCount, LocaleID: LongInt; DispIDs: Pointer): HResult; stdcall;
    function Invoke(DispID: LongInt;const IID: TGUID; LocaleID: LongInt;
      Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer):
HResult; stdcall;
  end;
function TDispatcher.GetTypeInfoCount(out Count: LongInt): HResult;
begin
  WriteLn('GetTypeInfoCount');
  Count := 0;
  Result := S_OK;
end;
function TDispatcher.GetTypeInfo(Index, LocaleID: LongInt; out TypeInfo):
HResult;
begin
  WriteLn('GetTypeInfo');
  Result := E_NOTIMPL;
end;
function TDispatcher.GetIDsOfNames(const IID: TGUID; Names: Pointer;
NameCount,
  LocaleID: LongInt; DispIDs: Pointer): HResult;
begin
  WriteLn('GetIDsOfNames');
  Result := S_OK;
end;
function TDispatcher.Invoke(DispID: LongInt; const IID: TGUID;
  LocaleID: LongInt; Flags: Word; var Params; VarResult, ExcepInfo,
  ArgErr: Pointer): HResult;
begin
  WriteLn('Invoke');
  Result := S_OK;
end;
procedure Test;
var
  D: IDispatch;
  V: Variant;
begin
  D := TDispatcher.Create;
  V := D;
  V.Hello();
end;
begin
  Test;
end.

Reply by email

Michael Van Canneyt
to Anthony Walter
Anthony Walter wrote
Is there any reason why the late binding of properties and methods through of IDispatch interface with the Variant type is not working on Linux?

Variant dispatching requires OS bindings.

They are enabled when the ComObj unit is included, and this is only included on windows.

Michael.

Reply by email

Anthony Walter
to Michael Van Canneyt

Thank you Micahel,

I was doing some research last night and found that there are two specific stubs in the System unit that are implemented by the ComObj unit. Specifically, a stub for safe call exception handling and dispatch invoke. I was working with my example and added my own OS agnostic implementations of those two functions. This eliminated the access violations.

I am not finished testing my solution, but in cases where late binding is desired, it ought to be possible to have it work on all platforms so long as the late binding is not attempting to cross process boundaries, which is common on Windows when using out of process servers such as Word or Excel. Perhaps my use case for late binding to a self contained scripting library might be useful for other people Free Pascal who do not run Windows. I am sure there are other possible use cases as well. In that light, it might be useful to integrate my eventual implementation into some unit included with FPC.

For anyone interested in this topic, late binding on platforms other than Windows, or the use of JavaScript, I have written on this subject in the past. The article I wrote below hosted on my blog can give you more insight into an aspect of the topic:

https://www.codebot.org/delphi/?doc=9573

Reply by email

Michael Van Canneyt
to Anthony Walter
Anthony Walter wrote 5 lines
Thank you Micahel, I was doing some research last night and found that there are two specific stubs in the System unit that are implemented by the ComObj unit. Specifically, a stub for safe call exception handling and dispatch invoke.

Yes, exactly.

I think the dispatch invoke callback/stub is in the variants unit: the VarDispProc procedural variable

Show quoted text 12 lines
I was working with my example and added my own OS agnostic implementations of those two functions. This eliminated the access violations. I am not finished testing my solution, but in cases where late binding is desired, it ought to be possible to have it work on all platforms so long as the late binding is not attempting to cross process boundaries, which is common on Windows when using out of process servers such as Word or Excel. Perhaps my use case for late binding to a self contained scripting library might be useful for other people Free Pascal who do not run Windows. I am sure there are other possible use cases as well. In that light, it might be useful to integrate my eventual implementation into some unit included with FPC.

Indeed.

I would be very grateful if you donate it, it would be useful for all FPC users !

Michael.

Reply by email