Accessing COM Objects

John via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Fri Jun 17 01:09:42 PDT 2016


On Wednesday, 15 June 2016 at 21:06:01 UTC, Joerg Joergonson 
wrote:
> My thinking is that CoCreateinstance is suppose to give us a 
> pointer to the interface so we can use it, if all this stuff is 
> crashing does that mean the interface is invalid or not being 
> assigned properly or is there far more to it than this?

The problem is Photoshop hasn't provided an interface with 
methods that can be called directly. They don't exist on the 
interface, hence them being commented out. It's a mechanism known 
as late binding (everything is done at runtime rather than 
compile time). You need to ask the interface for the method's ID, 
marshal the parameters into a specific format, and then "invoke" 
the method using that ID.

And you're not going to like it. Here's an example just to call 
the "Load" method:

   // Initialize the Photoshop class instance
   IDispatch psApp;
   auto iid = IID__Application;
   auto clsid = CLSID_Application;
   assert(SUCCEEDED(CoCreateInstance(&clsid, null, CLSCTX_ALL, 
&iid, cast(void**)&psApp)));
   scope(exit) psApp.Release();

   // Get the ID of the Load method
   auto methodName = "Load"w.ptr;
   auto dispId = DISPID_UNKNOWN;
   iid = IID_NULL;
   assert(SUCCEEDED(psApp.GetIDsOfNames(&iid, &methodName, 1, 0, 
&dispId)));

   // Put the parameters into the expected format
   VARIANT fileName = {
     vt: VARENUM.VT_BSTR,
     bstrVal: SysAllocString("ps.psd"w.ptr)
   };
   scope(exit) VariantClear(&fileName);

   DISPPARAMS params = {
     rgvarg: &fileName,
     cArgs: 1
   };

   // Finally call the method
   assert(SUCCEEDED(psApp.Invoke(dispId, &iid, 0, DISPATCH_METHOD, 
&params, null, null, null)));

tlb2d only outputs the late-bound methods as a hint to the user 
so they know the names of the methods and the expected parameters 
(well, it saves looking them up in OleView). Had Photoshop 
supplied a compile-time binding, you could have just called 
psApp.Load(fileName) like you tried.

It's possible to wrap that ugly mess above in less verbose code 
using native D types, and the Juno COM library mentioned earlier 
enabled that, but the code is quite ancient (and is part of and 
depends on a larger library). I've been slowly working on a more 
modern library. You'd be able to just write this:

   auto psApp = makeReference!"Photoshop.Application"();
   psApp.Load("ps.psd");

But I don't know when it'll be ready.


More information about the Digitalmars-d-learn mailing list