Jump to content

Interfaces


trancexx
 Share

Recommended Posts

One of new features AutoIt have is ability to create and use objects that are not necessarily defined as of "late bound" type. These object do not support late binding in terms of Automation.

However they can be used through special technique of late binding developed for the needs of AutoIt.

What is Interface? Without giving head hurting definitions, I'll say that Interface describes object.

In order for new feature to function correctly, interface definition has to be specified by the user prior object creation. Interface definition in context of AutoIt is string, so called "interface tag" or "interface definition string".

They list the names of all interface methods as well as types of return values for each of them including parameter types.

To show how to create tags I will use IUnknown interface even though you will very rarely (never?) do that since it's done by AutoIt internally for COM objecs. Follow that link and you will see that this interface define three methods, alphabetically AddRef, QueryInterface and Release.

It's very important that vtable order of method appearance is respected, so the methods are: QueryInterface, AddRef and Release.

IUnknown::QueryInterface is described here:

HRESULT QueryInterface(
  [in]   REFIID riid,
  [out]  void **ppvObject
);

Translated to AutoIt that would be:

"QueryInterface hresult(clsid;ptr*);"

IUnknown::AddRef

ULONG AddRef();

"AddRef dword();"

IUnknown::Release

ULONG Release();

"Release dword();"

Complete interface description string would be:

$tagIUnknown = "QueryInterface hresult(clsid;ptr*); AddRef dword(); Release dword();"

Languages that support early binding have Interfaces definitions written for you inside different SDKs.

For example, Visual Studio SDK includes all of the Interfaces definitions you would ever need for Windows programming.

The plan is to add interface definitions (common) to AutoIt in form of includes. What needs to be defined is precise way of doing it.

My idea is to use, what I call, Interface Files. These files are basically au3 scripts since they are read by the interpretter.

Files should not include any functions whatsoever. This is very important, no code inside, only "resources". Every interface definition have interface identifier - GUID, class identifier - GUID (if one exists) and interface tag.

Since I'm aware that my ideas are not necesarily the best, I would like others to say their thoughts and ideas about this.

Edited by trancexx
Better wording

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

So you are saying we treat these in pretty much exactly the same way we treat structures? Documenting it would be interesting, as you can't really have a single header documenting all the methods exposed by an interface... Perhaps the header should have sections, something like:

; #INTERFACE# ===================================================================================================================
; Name...........: $tagIUnknown
; Description ...: The fundamental interface from which all objects are derived
; GUID ..........: {00000000-0000-0000-C000-000000000046}
; Author ........: 
; Remarks .......: 
; Related .......: 
; #METHOD# ======================================================================================================================
; Name...........: QueryInterface
; Description ...: Retrieves pointers to the supported interfaces on an object.
; Syntax.........: IUnknown::QueryInterface( riid, ppvObject )
; Parameters ....: riid             - [in] The identifier of the interface being requested.
;                  ppvObject        - [out] The address of a pointer variable that receives the interface pointer requested in
;                                     the riid parameter. Upon successful return, *ppvObject contains the requested interface
;                                     pointer to the object. If the object does not support the interface, *ppvObject is set to
;                                     NULL.
; Return values .: This method returns S_OK if the interface is supported, and E_NOINTERFACE otherwise. If ppvObject is NULL,
;                  this method returns E_POINTER.
; Author ........: 
; Modified.......: 
; Remarks .......: For any one object, a specific query for the IUnknown interface on any of the object's interfaces must always
;                  return the same pointer value. This enables a client to determine whether two pointers point to the same
;                  component by calling QueryInterface with IID_IUnknown and comparing the results. It is specifically not the
;                  case that queries for interfaces other than IUnknown (even the same interface through the same pointer) must
;                  return the same pointer value.
; Related .......: 
; Link ..........: @@MsdnLink@@ IUnknown::QueryInterface
; Example .......: 
; #METHOD# ======================================================================================================================
; Name...........: AddRef
; Description ...: Increments the reference count for an interface on an object. This method should be called for every new copy
;                  of a pointer to an interface on an object.
; Syntax.........: IUnknown::AddRef(  )
; Parameters ....: None
; Return values .: The method returns the new reference count. This value is intended to be used only for test purposes.
; Author ........: 
; Modified.......: 
; Remarks .......: Objects use a reference counting mechanism to ensure that the lifetime of the object includes the lifetime of
;                  references to it. You use AddRef to stabilize a copy of an interface pointer. It can also be called when the
;                  life of a cloned pointer must extend beyond the lifetime of the original pointer. The cloned pointer must be
;                  released by calling IUnknown::Release.
; Related .......: IUnknown::Release
; Link ..........: @@MsdnLink@@ IUnknown::AddRef
; Example .......: 
; #METHOD# ======================================================================================================================
; Name...........: Release
; Description ...: Decrements the reference count for an interface on an object.
; Syntax.........: IUnknown::Release(  )
; Parameters ....: None
; Return values .: The method returns the new reference count. This value is intended to be used only for test purposes.
; Author ........: 
; Modified.......: 
; Remarks .......: When the reference count on an object reaches zero, Release must cause the interface pointer to free itself.
;                  When the released pointer is the only existing reference to an object (whether the object supports single or
;                  multiple interfaces), the implementation must free the object.
; Related .......: IUnknown::AddRef
; Link ..........: @@MsdnLink@@ IUnknown::Release
; Example .......: 
; ===============================================================================================================================
Global Const $tagIUnknown = "QueryInterface hresult(clsid;ptr*); AddRef dword(); Release dword();"

That's essentially a struct header with GUID added, followed by function headers. It would mean a rethink of the way headers are parsed... But there's no way to do it with the current system I don't think, that's as close at it will get.

Link to comment
Share on other sites

Well, no.

Interface describes the object. We shouldn't be describing objects' methods, only interface. Object documentation is doing what you did and that's up to object developer (e.g. Microsoft) to describe.

Edited by trancexx

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

Massive headers in the source files need to go away entirely so that suggestion will never happen.

There are what, 3 things for each interface? I don't see why we don't use a single file to define them. A single page in the documentation can list the interfaces with a note that more information should be sought elsewhere.

Link to comment
Share on other sites

Link to comment
Share on other sites

You're going to add dozens of very small files if you do that. Why? Explain why one file is a bad idea.

Define small.

One file is bad idea because different interfaces logically don't belong together. It would be mixing apples and oranges. For example memory management shouldn't be inside the same file as imaging (WIC).

To show how big the files are I'm attaching one file with StructuredStorage interfaces definitions: StructuredStorage.intfc.au3

That file is around 8kB in size. Bw, data types in there may not be correct (it's written before ObjCreateInterface function).

I estimate that average size of every file defining interfaces per API is 15-20 kB. Is that small?

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

I'm interested in why you listed the name before the return type in the interface definition.

There are several reasons for that:
  • It's common Automation practice
  • It's more intuitive
  • Doesn't collide with rules used for similar definitions in rest of the language (e.g. callbacks)

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

Average AutoIt programmer will have no idea what to do with the interfaces. Remember here that the average AutoIt programmer probably hardly ever touches code. Natural solution is UDFs to be written around them eventually. So these interfaces are for the writers of UDFs and skilled programmers. These will know how to look the interfaces up and write the interfaces down for themselves.

I suspect it is to solve people using the same interface with different definitions, but does this really matter? Explain please the reasoning behind defining all Windows interfaces at once, and not letting UDF writers do it when they need it.

Link to comment
Share on other sites

Average AutoIt programmer will have no idea what to do with the interfaces. Remember here that the average AutoIt programmer probably hardly ever touches code. Natural solution is UDFs to be written around them eventually. So these interfaces are for the writers of UDFs and skilled programmers. These will know how to look the interfaces up and write the interfaces down for themselves.

I suspect it is to solve people using the same interface with different definitions, but does this really matter? Explain please the reasoning behind defining all Windows interfaces at once, and not letting UDF writers do it when they need it.

No, not all interfaces. That wouldn't be reasonable. Most commonly (to be) used interfaces.

Writing UDFs around these objects is something that should be avoided. I would reject any attempt of anyone to submit something like that. Wrappers around wrappers around wrappers around wrappers around real code is not acceptable primarily because it defeats the main purpose of object existence.

Objects in AutoIt were neglected before because the code handling them wasn't ever finished and was in fact build on some basic wrong premises causing strange coding situations. Some parts of that confusion is handled already, the rest will be handled very shortly. After that objects can take their place in AutoIt scripting the way they should long time ago.

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

Ok, my next question is a bit off topic then. How can we help the novice programmers be able to work better with these interfaces? This seems more vital now if we don't want to write UDFs around them. Good documentation is the first, in help file references to interface documentation. Maybe examples. Lots of code on forums using a bunch of interfaces. Maybe old code rewritten.

What's the second? Is this a job for IDE? Aka intellisense.

Link to comment
Share on other sites

First step and 3/4 of overall process is taking the burden of creating definitions. It may be boring or tedious job, but it needs done.

Is this community (the creme) capable of that? My honest answer is I don't know. This community shoved that it can't handle even the simplest tasks, however I have faith. Individuals do exist. Motivating them to do community's job is hard.

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

Define small.

One file is bad idea because different interfaces logically don't belong together. It would be mixing apples and oranges. For example memory management shouldn't be inside the same file as imaging (WIC).

To show how big the files are I'm attaching one file with StructuredStorage interfaces definitions: StructuredStorage.intfc.au3

That file is around 8kB in size. Bw, data types in there may not be correct (it's written before ObjCreateInterface function).

I estimate that average size of every file defining interfaces per API is 15-20 kB. Is that small?

That's a horrible example. 28% of that file is the string:

;===============================================================================

Anyway, we'll see. When you write the interfaces out like you do they take up a lot of lines but in the end there still isn't much data there. I fully realize that one single large file may not be the best idea but I do not think a ton of small files are, either.

Others bring up a good point I'll expand on. Why should we be defining these at all? Where do we draw the line? Some of the interfaces are rather esoteric. Do we define those, too? Really, how much stuff is built into Windows that users will frequently want to access but isn't automation enabled? The two best examples that have come up so far are ITaskbarList and an undocumented interface for sound. I'm not saying there aren't others, of course, but just how much stuff is really out there? Isn't this whole thing rather esoteric to begin with? Most "common" objects are automation enabled.

Link to comment
Share on other sites

I use a combo of (courtesy of ProgAndy) in SMF to extract the shell thumbnail preview pictures.

Edit: I rant about the usefulness of an IContextMenu interface implementation.

Edited by KaFu
Link to comment
Share on other sites

  • 3 weeks later...

Average AutoIt programmer will have no idea what to do with the interfaces. Remember here that the average AutoIt programmer probably hardly ever touches code. Natural solution is UDFs to be written around them eventually. So these interfaces are for the writers of UDFs and skilled programmers. These will know how to look the interfaces up and write the interfaces down for themselves.

I feel this is true right now, but wont be true in the future as more and examples are shown. The fact that the vtables are not listed on the msdn makes looking up the interface that much more of a pain in the ass (especially if you dont have VS installed). With a rich stack of defined interfaces, more people will begin to use them or at least try.

No, not all interfaces. That wouldn't be reasonable. Most commonly (to be) used interfaces.

Writing UDFs around these objects is something that should be avoided. I would reject any attempt of anyone to submit something like that. Wrappers around wrappers around wrappers around wrappers around real code is not acceptable primarily because it defeats the main purpose of object existence.

Objects in AutoIt were neglected before because the code handling them wasn't ever finished and was in fact build on some basic wrong premises causing strange coding situations. Some parts of that confusion is handled already, the rest will be handled very shortly. After that objects can take their place in AutoIt scripting the way they should long time ago.

All in all I think your format for the interfaces looks fine. I fully agree with Valik about the small headers comment. Author, a link to the interface on msdn, and maybe a small description of what the entire interface is for. Not a description for each method and property. What does the #interface statement do? Is that something that will be required when defining one thats not already defined?

That's a horrible example. 28% of that file is the string:

;===============================================================================

Anyway, we'll see. When you write the interfaces out like you do they take up a lot of lines but in the end there still isn't much data there. I fully realize that one single large file may not be the best idea but I do not think a ton of small files are, either.

Others bring up a good point I'll expand on. Why should we be defining these at all? Where do we draw the line? Some of the interfaces are rather esoteric. Do we define those, too? Really, how much stuff is built into Windows that users will frequently want to access but isn't automation enabled? The two best examples that have come up so far are ITaskbarList and an undocumented interface for sound. I'm not saying there aren't others, of course, but just how much stuff is really out there? Isn't this whole thing rather esoteric to begin with? Most "common" objects are automation enabled.

I think the most important reason to be defining these is that unlike DllCall, we cant just point the user to the msdn to get all the information, mainly the vtable. Considering these are all just constants, Im confused on why your hesitant about adding them? I completely understand an infrequently used function not getting added to the UDFs because thats more code developers have to maintain, but when it comes to constants, even if used rarely, I don't see how that could hurt. What are the downsides? Edited by Beege
Link to comment
Share on other sites

I think the most important reason to be defining these is that unlike DllCall, we cant just point the user to the msdn to get all the information, mainly the vtable.

I feel that way, too. If the interfaces are not added as files, there should be a library with definitions in the wiki or so which is officially linked in the helpfile I think. Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

I completely understand an infrequently used function not getting added to the UDFs because thats more code developers have to maintain, but when it comes to constants, even if used rarely, I don't see how that could hurt. What are the downsides?

You seem to think these are going to be small. Some of them will be. A lot of them will not be.
Link to comment
Share on other sites

You seem to think these are going to be small. Some of them will be. A lot of them will not be.

Ok so its more of a package size problem or a road that leads to it? If thats the case then has the idea of having an extras or advanced package been brought up? Something similar to how you handled scite. You have the one that comes with the standard package, then you have the other (Scite4Autoit) thats filled with tons of extras for the more experinced users. The standard installer would include only the very common interface definitions, and all others in the advanced package. This could also be a way to add some of the very well written, but not popular enough UDFs floating around the forums.
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...