Lisp HUG Maillist Archive

How to get COM/Automation running under LispWorks

Well I spend quite a bunch of time with trying to understand how things have
to work.
I found quite a few bugs on my way which the excellent support of Xanalys
fixed
immediatly. So before anything else thanks (especially to Dave) for helping
me so much.

Before you start to get things going you may
Before we can start our journey I suggest asking Xanalys for the sended
patches.
CL-USER 29 : 2 > (directory "*.fsl")
(#P"p:/LispWorks/lib/4-2-0-0/private-patches/type-library-handle-parent-inte
rfaces.fsl"

#P"p:/LispWorks/lib/4-2-0-0/private-patches/find-dispatch-method-or-property
-in-interface.fsl"

#P"p:/LispWorks/lib/4-2-0-0/private-patches/com-handle-parent-interfaces.fsl
"
 #P"p:/LispWorks/lib/4-2-0-0/private-patches/autoload-com-tools.fsl")

This is the needed load.lisp file to get all this patches applied
(let ((location (pathname-location *load-pathname*)))
  (flet ((load-one-private-patch (path sequence)
           (scm:require-private-patch (merge-pathnames path location)
sequence)))

    ;; Example form to load a :system sequence patch from the file my-patch.
    ;; (load-one-private-patch "my-patch" :system)
	(load-one-private-patch "com-handle-parent-interfaces" :COM)
	(load-one-private-patch "type-library-handle-parent-interfaces"
:AUTOMATION)
     (LOAD-ONE-PRIVATE-PATCH "find-dispatch-method-or-property-in-interface"
:AUTOMATION)
	(LOAD-ONE-PRIVATE-PATCH "autoload-com-tools" :full)
    ))

Now what I was going to do depended on the Scripting.FileSystemObject from
the Windows
Scripting Host an example using this look like this in VB or VBScript
Private Sub Fun_1()
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set Drive = fso.GetDrive("C:")
    MsgBox "On C: are " & Drive.FreeSpace / (1024# * 1024#) & " MB left"
End Sub

Or something else along this lines.
This are the steps it took to get things going:
- Search for the library which provided the needed functionality. (I have
used ScriptingSpy and after
applying the patch "autoload-com-tools" the Tools provided with LispWorks
(See manual COM chapter 5))
- the needed functinality can be found in scrrun.dll
- I copied this file to the working directory. than you have to rename it to
	scrrun.tlb (just informing that it should be treated as a
:midl-type-library-file does not work)
- Then I set-up a defsys-lisp file
(in-package :cl-user)

(require "com")
(require "automation")

(defsystem com-example ()
  :members
  (("scrrun.tlb" :type :midl-type-library-file)
   "foo.lisp"))

- you know can compile/load the system
- I wrote some (not so useful ;-) Scripts
(defvar *fso-object* nil)
(defun initialize ()
  (com:co-initialize) ; prior to any use
  (setf *fso-object* (com:create-object :progid
"Scripting.FileSystemObject")))

(initialize)


(defun com-test-1 ()
  (let ((folder (com:call-dispatch-method (*fso-object* i-file-system
get-folder) "c:\\")))
    (capi:display-message "~A~%" (com:call-dispatch-method (folder i-folder
type)))))

(defun com-test-3 ()
  (let ((folder (com:call-dispatch-method (*fso-object* file-system-object
get-folder) "c:\\")))
    (capi:display-message "~A~%" (com:call-dispatch-method (folder folder
type)))))




(defun com-test-2 ()
  (let* ((file-name (capi:prompt-for-string "Give me a file name please")))
    (capi:display-message "~A" (com:call-dispatch-method
                                (*fso-object* i-file-system
get-absolute-path-name)
                                file-name))))

(defun com-test-4 ()
   (let ((drive-list (com:call-dispatch-get-property
                       (*fso-object* i-file-system drives))))
   (flet ((disp-info (drive-letter free-space)
            (capi:display-message "~A has ~A GB free space left"
                                  drive-letter free-space)))
     (com:do-collection-items (drive drive-list)
       (when (com:call-dispatch-get-property
              (drive drive is-ready))
         (disp-info (com:call-dispatch-get-property
                     (drive i-drive drive-letter))
                    (float (/
                            (com:call-dispatch-get-property
                             (drive i-drive free-space))
                            (* 1024 1024 1024)))))))))


com-test-1 is how things have to be handeled without the patches
com-test-3 shows how it got a bit easier with the patches applied.


Remarks:
This are my impressions about the COM stuff.
- it seems to me as if I had to provide too much information on my own and
the different
	com:call-dispatch functions make things not easier. As I understand the
created COM Object
	does have all this information availabel (what interface it implements etc,
nevertheless do I have to re-write it by myself.
- The com:call-dispatch-stuff is IMHO too long winded.
- the naming conventions differ between COM and Automation. If you use the
tools provided with
	LispWorks you find the COM convention. which looks like this
	(com:define-com-method (i-drive get-drive-letter)
    ((this com::c-generic-class-factory)
     (pbstr-letter :out))

  ;; Insert implementation here

  com:s_ok)
	You see get-drive-letter. If you are using the Automation stuff you do not
have to use this
name but the name without the get see e.g com-test-4
- the com:call-dispatch stuff reminds me of the send syntax from
LispMachines. It's IMHO not
very Lisp-ish the :send syntax was superseeded by the CLOS accessor
functions which I think are
much easier to understand.

Suggestion (for discussion)
- Wouldn't it make sense to handle COM or Automation Objects like CLOS
Objects?
- things would be much easier to write, read and understand e.g
(defun com-test-1 ()
  (let ((folder (com:call-dispatch-method (*fso-object* i-file-system
get-folder) "c:\\")))
    (capi:display-message "~A~%" (com:call-dispatch-method (folder i-folder
type)))))
would get
(defun com-test-1-fictious()
	(let ((folder (get-folder *fso-object* "c:\\")))
	   (capi:display-message "~A~%" (type folder)))))

Even in that simple example think the advantages are obvious, IMHO.

I hope this mail will help someone else trying to get things going.

Conclusion:
Having the possibility to use COM Objects enhances the usefullness of
LispWorks
massively. It's was the "right" more IMHO. The easier the briding to the
"outer-world" the better
for people using Lisp. I do feel nevertheless that the API should been
improved, that it's easier
to use the available facilities.

Again many thanks to the Xanalys Support Team. You have done a remarkable
job.

Regards
Friedrich





Re: How to get COM/Automation running under LispWorks

Unable to parse email body. Email id is 238

Updated at: 2020-12-10 09:02 UTC