arsd 11.2 - COM dispatch revamp

Posted 2023-10-02

A user dug out my old arsd.com module and tried to use it to automate Word and Excel. It didn't work out of the box, but I was able to patch it up to work similarly to Python.

Core D Development Statistics

In the community

Community announcements

See more at the announce forum.

arsd 11.2

I'm finishing this blog late, the tag actually came in October 9th, but it was mostly for this week in D lol.

Five major things:

  • Transparent notification area icons work better in simpledisplay on Linux now. This code also will support translucent windows in general at some point, but right now I just focused on the icon windows specifically.
  • terminal.d had a performance regression due to checking grapheme size for cursor tracking. It reverted that and instead asks the terminal for cursor updates when you query the cursorX/Y properties.
  • com got a bit of a revamp and can be used to automate programs like Word and Excel similarly to Python's dispatch object now.
  • simpledisplay OS X Cocoa implementation basically works now... so long as you use dmd. ldc doesn't support extern(Objective-C) and I didn't want to write the code without it. Hopefully that will be implemented soonish. There's plenty of bugs and incomplete features still, but it is to the point where a minigui application can run on it with custom widgets, which exercises a decent chunk of the sdpy api, so it is getting caught up finally.

    Hit a compiler bug in the way - any objc method that returns a large struct is suspect in the dmd codegen. There's an extra pointer on the stack you need to pop off with inline asm or everything gets out of alignment. That wasted some time, but ultimately, I just used a method that returned a smaller struct instead lol.

  • My webtemplate.d is now available on dub.

I'll go into a little detail about com.d, but the others I think are adequately described already. See last week's blog entry for more about the OS X Cocoa thing. Maybe I'll write more about the transparent thing next week if I have time.

Anyway, the arsd com file has been around since about 2013 when I wrote it to help a Stack Overflow user. The original thing was to call into some D code from JScript and focused on an IDispatch server implementation. I didn't know much about COM before then, but I did manage to make the basics work.

However, then I essentially dropped it until 2019, when I expanded it to have a basic IDispatch client implementation too, hoping to do for C# what arsd.jni did for Java. Didn't really work though and got dropped again.

This time, someone asked if it could be used to run Microsoft Word from the outside, and the answer was no, but the pieces were there to make it work with a bit of expansion; I already had some IDispatch impl and that's the main thing needed. So I hacked together some stuff and... it didn't work.

There's three pieces that needed attention: methods vs properties, CLSCTX constants, and GetObject vs CreateObject. The last one is simple: I didn't realize there was a separate GetObject function (I really know very little about this area!), so I added a call to it and found joy.

The CLSCTX constants are a bit bizarre. It was unclear to me what ones you're supposed to use, and the set that works for one application doesn't necessarily work for another application. Annoying, and I expect I'll have to come back to this more later, but meh it works for me for now.

But the method vs property one is a bit of a pain in D with a dispatch implementation. See, in D, methods and properties are the same thing; properties ARE methods, and if you have an opDispatch return a callable object or possibly even an assignable object, you will have to use some extra syntax to both call the property get method and then call its return value too. This is a little annoying, since the @property annotation COULD clear it up, but this hasn't been implemented for... like 12 years, so I don't expect it to change.

Instead, I settled on doing a double lookup - first try to dispatch as a property, and if that fails, try as a method too. It worked! But is less than ideal. In other places, I've used different sets for obj.properties.thing and obj.methods.thing to let the user specify, but some of them aren't even obvious what they're supposed to be when given examples off the net, so I just will keep it as it is.

The user still declined to use my library, so eh, it'll probably go on hold again for a while since I have no pressing need for it either, but this is still a little more movement toward it actually just working some day. Even as it is though, with its extra () and double lookups sometimes, and only supporting strings and ints right now (adding more types is fairly straightforward but I have so many other things to do), it is still somewhat useful; I could control Word and Excel with it successfully for the basics at least.