niermann / temscript

Python wrapper for the scripting interface of Thermo Fisher Scientific and FEI microscopes.
Other
42 stars 14 forks source link

get_index / put_index #8

Closed azazellochg closed 2 years ago

azazellochg commented 2 years ago

Hello @niermann , I'm using your scripting API and it's great! I'm trying to add advanced scripting functions in my fork. Since I'm not familiar with COM/ctypes, may I ask how do you know get_index and put_index? I couldn't figure it out..

It looks like the methods are numbered first (starting from 7), followed by properties.

niermann commented 2 years ago

Hi @azazellochg

this is the fiddly part of using COM interfaces straight with ctypes...

At first you need the header files for the COM interface. This already some time ago, when I created them for the microscope's interface, so I can't remember how I did it. There might be a way using the COM/OLE-Viewer included in the Visual C++ SDK (search the internet for something like "header files from type library").

Alternatively (according to the TEM scripting documentation), you may include the line #import "stdscript.tlb" named_guids into a Visual C++ project (you might also use the stdscript.dll instead of the tlb file). This should also generate the header files (but with extension tlh).

The put_index & get_index indices are simply slots in the virtual method table (VTLB) of the respective interfaces. So simply count the virtual methods occuring in the interface declaration. However, the base classes might already include some virtual methods, these have to be added to obtain the index. IUnkown already declares 3 virtual methods, IDispatch declares in total 7 virtual methods (including those of IUnknown).

As Example this is a part the Illumination interface declaration from the header file:

struct __declspec(uuid("ef960690-1c38-11d3-ae0b-00a024cba50c"))
Illumination : IDispatch
{

[...]

//
// Raw methods provided by interface
//

  virtual HRESULT __stdcall raw_Normalize (
    enum IlluminationNormalization nm ) = 0;
  virtual HRESULT __stdcall get_Mode (
    /*[out,retval]*/ enum IlluminationMode * pMode ) = 0;
  virtual HRESULT __stdcall put_Mode (
    /*[in]*/ enum IlluminationMode pMode ) = 0;
  virtual HRESULT __stdcall get_SpotsizeIndex (
    /*[out,retval]*/ long * pSS ) = 0;
  virtual HRESULT __stdcall put_SpotsizeIndex (
    /*[in]*/ long pSS ) = 0;

[...]

};

Here the VTLB index of raw_Normalize is 7 (due to the methods in IDispatch). The "get_index" for Mode is then 8, and the "put_index" of Mode is 9. "get_index" for SpotSizeIndex is 10, "put_index" is 11 and so on.

azazellochg commented 2 years ago

Thank you for the explanation, @niermann ! I think I could get the same info using comtypes (listing com object methods) which is easier for me than digging c++:

INFO:root:illum uuid: {EF960690-1C38-11D3-AE0B-00A024CBA50C}
INFO:root:illum methods:
INFO:root:(<class 'ctypes.HRESULT'>, 'Normalize', (<class 'ctypes.c_long'>,), ((0, 'nm'),), (1, 'Normalization of illumination system'), 'Normalization of illumination system')
INFO:root:(<class 'ctypes.HRESULT'>, '_get_Mode', (<class 'ctypes.wintypes.LP_c_long'>,), ((10, 'pMode'),), (11, 'Illumination Mode (nano/microprobe)', 'propget'), 'Illumination Mode (nano/microprobe)')
INFO:root:(<class 'ctypes.HRESULT'>, '_set_Mode', (<class 'ctypes.c_long'>,), ((1, 'pMode'),), (11, 'Illumination Mode (nano/microprobe)', 'propput'), 'Illumination Mode (nano/microprobe)')
INFO:root:(<class 'ctypes.HRESULT'>, '_get_SpotsizeIndex', (<class 'ctypes.wintypes.LP_c_long'>,), ((10, 'pSS'),), (12, 'Index for the spotsize', 'propget'), 'Index for the spotsize')
INFO:root:(<class 'ctypes.HRESULT'>, '_set_SpotsizeIndex', (<class 'ctypes.c_long'>,), ((1, 'pSS'),), (12, 'Index for the spotsize', 'propput'), 'Index for the spotsize')
...
azazellochg commented 2 years ago

@niermann since you are using raw ctypes and not comtypes lib would this mean that if FEI/TFS adds more properties to some interfaces in the new scripting versions, some indexes would have to be renumbered because the headers will change?

niermann commented 2 years ago

Yes, probably comtypes will return the VTBL entries in order. When I started temscript along time ago, I was not aware of comtypes, later I wanted to avoid the dependency, since I'm limited with what I can install on the TEM PC. So I never used it for accessing the scripting of the microscope.

Nothing hinders FEI/TFS to change the indices in future versions. However, they would break the binary compatibility for preexisting scripting users, so it is most unlikely that they change these indices. It is safe for them to add more properties to the end of the VTBL, which will keep existing indices unchanged. If they would remodel there scripting interfaces the sane choice would be to introduce new interface classes (from hearsay I get, they did already introduced a newer Gun interface in newer scripting versions, while keeping the original interface intact).

azazellochg commented 2 years ago

Thanks @niermann , if I may ask one more question: how can I get enums numbers/order? Did you use the order from documentation?

niermann commented 2 years ago

The generated header files also contain the enums with the value/name combinations. As comtypes seems to have a type lib parser, perhaps there is a way to use comtypes to also obtain their values.

azazellochg commented 2 years ago

Great, I'll have a closer look!