Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion

Share Me

  • Please share this topic with your friends. Click any of the icons below:
  • Twitter
  • facebook
  • reddit
  • email

LMDScripting: wrapped record objects work with native pascal but not VBScript?

I have had trouble in our main application using record properties on objects, working with native pascal scripting but not with VBScript.  Some two years ago with LMD2014 and possibly earlier OS versions the record properties were working....

(I am using LMD 2017.4, under Win10)
I have gone back to one of the demo programs, namely "DelphiMapping" and example 4 therein, relating to records, and in particular system.TPoint is used as an example wrapped record (descendant class of TLMDRecordWrapper)
-----------------------------------------------------
procedure Main;
var
  rec, recstr;
  samerec, anotherrec;
begin
    // Creating and using records:

    rec     := TPoint.Create;
    rec.X   := 3;
    rec.Y   := 5;
    recstr  := '(' + IntToStr(rec.X) + ', ' + IntToStr(rec.Y) + ')';
...
    MessageList.Lines.Add('Created TPoint record: ' + recstr);

    // Copying records:

    samerec    := rec;      // Just another ref to same record object.
    anotherrec := rec.Copy; // Real copy.
-----------------------------------------------------

THIS ALL WORKS
HOWEVER when I do a VBScript version, 
-----------------------------------------------------
...    
   rec     = TPoint.Create
    rec.X   = 3
    rec.Y   = 5
...
-----------------------------------------------------

and run inside the debugging demo, the create line seems to run but after assigning the properties the object is still "empty"
Am I not creating the object correctly with my VBscript syntax?

Have also tried:
  rec =CreateObject("TPoint")
... and other variants but get OLE errors so assume my syntax is completely wrong with these.

Comments

  • 7 Comments sorted by Votes Date Added
  • Hi,

    But, it works in the demo:

        dim rec = new TPoint
        rec.X = 3
        rec.Y = 5
        dim recstr = "(" + CStr(rec.X) + ", " + CStr(rec.Y) + ")"

    May be the problem is that you do not use "new" VB operator?..
  • It is not working for me I'm afraid. (LMD2017.4, win10)

    I used the supplied "Hellow World" demo as a tester.

    Adding   P := TPoint.Create; into the slPascal default version works fine.

    But simplifying it and changing to language to slVBScript:

    sub Main(a,b)
    '    Creating and using records
        dim rec = new TPoint
        rec.X   = 3
        rec.Y   = 5
    end sub

    I get the error "Expected End of Statement [line:3 pos:12]"

    Changing line 3 to:
     
    set rec = new TPoint

    ...gives me "Class not defined 'TPoint" [line:3, pos:4]

    The pascal can find TPoint OK so why the VBscript can't has me concerned.

    I am not very comfortable in VBscript myself (!!) but we have a sizeable library of VBscripts we use for parametric shape creating which all used to work, and no longer function, they were using the "TPoint.Create" syntax.  (Actually not TPoint , but TVector, one of our own record cwrapper classes) Some of the scripts are slPascal and these still function correctly.

    For example this snippet used to work:
    ...
      ' place radial dimension
      set lDim = dimensions.LinearDimensionByName("Width")
      lDim.OriginStart  = Vector(width, 0.0)
    ...

    Now gives us a Type mismatch error, lDim is a class, Originstart is a property of type TVector.

    Vector(x,y,) is a function returning a TVector...

    I tried assigning record's fields individually:

      ' place radial dimension
      set lDim = dimensions.LinearDimensionByName("Width")
      lDim.OriginStart.X  = width
      lDim.OriginStart.Y = 0

    .. and this runs without script errors, but leaves ldim.originstart still 0,0, ie it fails to correctly assign the values. 

    I tried switching to slNativeVB and can make it work with that, but there's syntax differences, such as needing to dim all variables before they are used.... I might as well change all the scripts to slPascal which is more readable to me;  but I do think something is broken re VBScript and records.  Or I'm missing something completely which is not impossible!!!...

  • Ok, I'll look again.
  • Posts: 0 Accepted Answer Vote Up0Vote Down
    Hi,

    I'm sorry for previous message, whwre I mistunderstood you and checked things in NativeVB lang.
    I just re-checked issue with HellowWorld demo, in which I've changed the Language to slVBScript and code in memo to the following:

    sub Main (p1, p2)

      set x = TPoint.Create
      x.X = 7

      if x.X = 7 then
        ShowMessage("Hello there")
      end if

    end sub

    And it worked well. OS - Win10. Delphi - I've checked in XE2 and 10.1
  • Thanks Balabuev,

    Its is working for me also now, i think i was making other syntactical errors.  The problem we are having with our existing script base seems however to be related to the wrapping of our own class TVector which works in itself, but does not seem to be assignable to our own wrapped object classes as a field property.

    eg (simplifying) we have  TDimension class, which has startpoint and endpoint read/write properties of type TVector.

    set v = TVector.create 
    v.x=1.1
    v.y=2.2

    ... works  OK.

    However 

    set mydim = TDimension.Create
    myDim.startpoint = v 

    ...then gives a type mismatch on the line myDim.startpoint = v 

    And again the pascal version of the script  still works.

    The problem seems to be related to a change in the LMD source, we used to override the following methods of TLMDClassWrapper

        class function  DoInstanceInvoke(Value: TObject; Index: Integer;
                                         const AArgs: TLMDDispArgs; AArgsSize: Integer;
                                         IsGet: Boolean): OleVariant; override;
        class function  DoClassInvoke(Value: TClass; Index: Integer;
                                      const AArgs: TLMDDispArgs; AArgsSize: Integer;
                                      PropGet: Boolean): OleVariant; override;

    ... with case statements implemented to access the methods and properties

    But these seem have gone and be deprecated/or unnecessary in the newer version of the code, however something in our implementation is tripping up with vbScript....  Anyway another developer here who worked on that update is having a look.

    Thanks for your help!!!

  • My colleague here Mark has investigated it (he tried to register on the forum but got a page not found error), so his comments below, again the problem is that we cant set properties on a record field of a class.
    eg in our Delphi source code we wrap something this ( creating TSomething_lmdsw  or similar using the wizards etc)

    TSomething = class(TObject)  
      m_point : TPoint;
      function getpoint:TPoint;
      procedure setPoint(const in_value:Tpoint);
      property point:TPoint read getPoint  write setPoint;
    ...
     TSomething.setpoint(const in_value:TPoint);
     begin
       m_point := in_value; 
      end ;

    and in our VBscript when we do
      
      set s = TSomething.Create
      set p = TPoint.Create
      p.x=10
      p.y=20
      ' all ok to here... but...
      s.point=P ' doesn't work, generates type mismatch errors, seems to be invoked with isGet=true instead of false
      s.point.x = p.x  'doesn't work either, no errors generated, but s.point.x  is not assigned, is still 0
     
    Again, this used to work in VBScript, and the pascal script still works.  Mark's change below seems to fix it:


    I
    investigated and found that for VBScript files setting properties invoked the
    getter instead of the setter.

    I think
    there may be a bug with Line 1647 of LMDSCTWrappers.pas in
    TLMDDispWrapper.Invoke

    When I
    added 'or DISPATCH_PROPERTYPUTREF' to the LowInvoke call the scripting
    continues to work for pascal scripting and starts to work again for vbscript.

     ie              

        vres
    := LowInvoke(item, TLMDDispArgs(Pointer(@vargs)^), argsz,

                         
    (Flags and (DISPATCH_PROPERTYPUT or DISPATCH_PROPERTYPUTREF)) = 0);

     I was
    wanting to debug this more but the project this is in uses Delphi 10.2 and the
    IDE is frequently unstable, so unstable for attempting to debug in this
    instance that I gave up with it.

     Line 5413
    of LMDSctScripter.pas also looks suspicious but I haven't investigated that.

  • Posts: 0 Accepted Answer Vote Up0Vote Down
    Hi,

    I've added DISPATCH_PROPERTYPUTREF as described in your message. As well, I've added DISPATCH_PROPERTYPUT to TLMDDispWrapperData.AddDispProp as shown:

      if AIsWritable then
      begin
        if AType() = varDispatch then
          invflag := invflag or DISPATCH_PROPERTYPUT or DISPATCH_PROPERTYPUTREF
        else
          invflag := invflag or DISPATCH_PROPERTYPUT;
      end;

    So,

      s.point=P       // now works
      set s.point=P   // also works
     
    However,

      s.point.x = p.x

    will not work, and it never worked before, because s.point returns record, which (in Delphi terms) is not an "L-Value".
Sign In or Register to comment.