Thread overview | |||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 13, 2016 Accessing COM Objects | ||||
---|---|---|---|---|
| ||||
I've been reading over D's com and can't find anything useful. It seems there are different ways: http://www.lunesu.com/uploads/ModernCOMProgramminginD.pdf which is of no help and requires an idl file, which I don't have. Then theres this http://wiki.dlang.org/COM_Programming which is also of no help: import std.stdio; import std.stdio, core.sys.windows.com, core.sys.windows.windows, std.exception, std.meta, std.traits; import std.utf, core.stdc.stdlib, core.sys.windows.objidl, core.sys.windows.ole2; pragma(lib, "ole32.lib"); GUID Guid(string str)() { static assert(str.length==36, "Guid string must be 36 chars long"); enum GUIDstring = "GUID(0x" ~ str[0..8] ~ ", 0x" ~ str[9..13] ~ ", 0x" ~ str[14..18] ~ ", [0x" ~ str[19..21] ~ ", 0x" ~ str[21..23] ~ ", 0x" ~ str[24..26] ~ ", 0x" ~ str[26..28] ~ ", 0x" ~ str[28..30] ~ ", 0x" ~ str[30..32] ~ ", 0x" ~ str[32..34] ~ ", 0x" ~ str[34..36] ~ "])"; return mixin(GUIDstring); } int main(string[] argv) { // Adobe Photoshop App 9.0 CLSID {c09f153e-dff7-4eff-a570-af82c1a5a2a8} // Adobe Photoshop App 9.1 CLSID {6DECC242-87EF-11cf-86B4-444553540000} auto CLSID_DOMDocument60 = Guid!("6DECC242-87EF-11cf-86B4-444553540000"); auto iid = IID_IUnknown; void* pUnk; auto hr = CoCreateInstance(&CLSID_DOMDocument60, null, CLSCTX_ALL, &iid, &pUnk); if (FAILED(hr)) throw new Exception("Error!"); writeln("Hello D-World!"); return 0; } Maybe my CLSID's are wrong. Got them from the registry. The exception triggers each time. Even if it worked, I wouldn't know how to use it. I can do this stuff in C# by simply dragging and dropping a dll into the references and it works fine but is a bit slow. I was hoping I could speed things up using D but it seems like COM isn't really supported, despite what several references say. |
June 13, 2016 Re: Accessing COM Objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Incognito | On Monday, 13 June 2016 at 01:22:33 UTC, Incognito wrote: > I can do this stuff in C# by simply dragging and dropping a dll into the references and it works fine but is a bit slow. I was hoping I could speed things up using D but it seems like COM isn't really supported, despite what several references say. Com *is* supported in D. I think it's better to work with interfaces rather than classes like the Wiki example: interface MyCOMType : IUknown {} Then when you get a pointer from CoCreateInstance or whatever, you cast it to the interface type and away you go. In your code, your problem is that CoCreateInstance is failing, not that D doesn't support COM. It will help you to find out what the actual value of 'hr' is. Possible values are listed at [1]. [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms686615(v=vs.85).aspx |
June 13, 2016 Re: Accessing COM Objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | On Monday, 13 June 2016 at 01:52:12 UTC, Mike Parker wrote:
> On Monday, 13 June 2016 at 01:22:33 UTC, Incognito wrote:
>
>> I can do this stuff in C# by simply dragging and dropping a dll into the references and it works fine but is a bit slow. I was hoping I could speed things up using D but it seems like COM isn't really supported, despite what several references say.
>
> Com *is* supported in D. I think it's better to work with interfaces rather than classes like the Wiki example:
>
> interface MyCOMType : IUknown {}
>
> Then when you get a pointer from CoCreateInstance or whatever, you cast it to the interface type and away you go.
>
> In your code, your problem is that CoCreateInstance is failing, not that D doesn't support COM. It will help you to find out what the actual value of 'hr' is. Possible values are listed at [1].
>
> [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms686615(v=vs.85).aspx
What interface are you talking about? How can I cast to something I don't have? I do not have a photoshop COM interface. Are you saying that if CoCreateInstance worked that I can then use the iid or pUnk to access the COM? Do I get the members by trial and error? pUnk.width? Even if CoCreateInstance passed, what do I do next?
|
June 13, 2016 Re: Accessing COM Objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Incognito | On Monday, 13 June 2016 at 02:08:22 UTC, Incognito wrote: > What interface are you talking about? How can I cast to something I don't have? I do not have a photoshop COM interface. Are you saying that if CoCreateInstance worked that I can then use the iid or pUnk to access the COM? Do I get the members by trial and error? pUnk.width? Even if CoCreateInstance passed, what do I do next? You have to define the interface yourself, extending from IUnknown, implementing whatever functions are available on the COM interface you want. Here's an example for the ID3D11Device interface: https://github.com/auroragraphics/directx/blob/master/d3d11.d#L1332 |
June 13, 2016 Re: Accessing COM Objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | On Monday, 13 June 2016 at 04:52:49 UTC, Mike Parker wrote: > On Monday, 13 June 2016 at 02:08:22 UTC, Incognito wrote: > >> What interface are you talking about? How can I cast to something I don't have? I do not have a photoshop COM interface. Are you saying that if CoCreateInstance worked that I can then use the iid or pUnk to access the COM? Do I get the members by trial and error? pUnk.width? Even if CoCreateInstance passed, what do I do next? > > You have to define the interface yourself, extending from IUnknown, implementing whatever functions are available on the COM interface you want. Here's an example for the ID3D11Device interface: > > https://github.com/auroragraphics/directx/blob/master/d3d11.d#L1332 Sorry. Hit send too soon. Once you've got your interface defined, you should be able to do this: MyCOMType mct; auto hr = CoCreateInstance(&CLSID_DOMDocument60, null, CLSCTX_ALL, &iid, &cast(void*)mct); It's been a long time since I worked directly with COM, so there are probably details I'm missing, but this is the general idea. |
June 13, 2016 Re: Accessing COM Objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Incognito | On Monday, 13 June 2016 at 01:22:33 UTC, Incognito wrote: > I've been reading over D's com and can't find anything useful. It seems there are different ways: > > http://www.lunesu.com/uploads/ModernCOMProgramminginD.pdf > > which is of no help and requires an idl file, which I don't have. > > Then theres this > > http://wiki.dlang.org/COM_Programming > > which is also of no help: > > import std.stdio; > > import std.stdio, core.sys.windows.com, core.sys.windows.windows, std.exception, std.meta, std.traits; > import std.utf, core.stdc.stdlib, core.sys.windows.objidl, core.sys.windows.ole2; > pragma(lib, "ole32.lib"); > > > GUID Guid(string str)() > { > static assert(str.length==36, "Guid string must be 36 chars long"); > enum GUIDstring = "GUID(0x" ~ str[0..8] ~ ", 0x" ~ str[9..13] ~ ", 0x" ~ str[14..18] ~ > ", [0x" ~ str[19..21] ~ ", 0x" ~ str[21..23] ~ ", 0x" ~ str[24..26] ~ ", 0x" ~ str[26..28] > ~ ", 0x" ~ str[28..30] ~ ", 0x" ~ str[30..32] ~ ", 0x" ~ str[32..34] ~ ", 0x" ~ str[34..36] ~ "])"; > return mixin(GUIDstring); > } > > int main(string[] argv) > { > > // Adobe Photoshop App 9.0 CLSID {c09f153e-dff7-4eff-a570-af82c1a5a2a8} > // Adobe Photoshop App 9.1 CLSID {6DECC242-87EF-11cf-86B4-444553540000} > > auto CLSID_DOMDocument60 = Guid!("6DECC242-87EF-11cf-86B4-444553540000"); > auto iid = IID_IUnknown; > > void* pUnk; > auto hr = CoCreateInstance(&CLSID_DOMDocument60, null, CLSCTX_ALL, &iid, &pUnk); > if (FAILED(hr)) > throw new Exception("Error!"); > > writeln("Hello D-World!"); > return 0; > } > > Maybe my CLSID's are wrong. Got them from the registry. The exception triggers each time. Even if it worked, I wouldn't know how to use it. > > I can do this stuff in C# by simply dragging and dropping a dll into the references and it works fine but is a bit slow. I was hoping I could speed things up using D but it seems like COM isn't really supported, despite what several references say. COM is supported in D. The difference is that C# hides all the plumbing behind nice classes. You're going to need Photoshop's COM interface to do anything with it. If you don't have a C header that you can translate into D, you could use a tool included in the Windows SDK called OleView. It will peek inside COM libraries and give you the interface definitions. As to why CoCreateInstance isn't working, make sure you're calling CoInitialize or CoInitializeEx beforehand. If it's still failing, use std.windows.syserror.sysErrorString(hr) to see if it gives you a reason. Otherwise, CLSCTX_ALL might be the culprit - try using CLSCTX_SERVER instead. |
June 13, 2016 Re: Accessing COM Objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to John | On Monday, 13 June 2016 at 07:40:09 UTC, John wrote:
> On Monday, 13 June 2016 at 01:22:33 UTC, Incognito wrote:
>> I've been reading over D's com and can't find anything useful. It seems there are different ways:
>>
>> http://www.lunesu.com/uploads/ModernCOMProgramminginD.pdf
>>
>> which is of no help and requires an idl file, which I don't have.
>>
>> Then theres this
>>
>> http://wiki.dlang.org/COM_Programming
>>
>> which is also of no help:
>>
>> import std.stdio;
>>
>> import std.stdio, core.sys.windows.com, core.sys.windows.windows, std.exception, std.meta, std.traits;
>> import std.utf, core.stdc.stdlib, core.sys.windows.objidl, core.sys.windows.ole2;
>> pragma(lib, "ole32.lib");
>>
>>
>> GUID Guid(string str)()
>> {
>> static assert(str.length==36, "Guid string must be 36 chars long");
>> enum GUIDstring = "GUID(0x" ~ str[0..8] ~ ", 0x" ~ str[9..13] ~ ", 0x" ~ str[14..18] ~
>> ", [0x" ~ str[19..21] ~ ", 0x" ~ str[21..23] ~ ", 0x" ~ str[24..26] ~ ", 0x" ~ str[26..28]
>> ~ ", 0x" ~ str[28..30] ~ ", 0x" ~ str[30..32] ~ ", 0x" ~ str[32..34] ~ ", 0x" ~ str[34..36] ~ "])";
>> return mixin(GUIDstring);
>> }
>>
>> int main(string[] argv)
>> {
>>
>> // Adobe Photoshop App 9.0 CLSID {c09f153e-dff7-4eff-a570-af82c1a5a2a8}
>> // Adobe Photoshop App 9.1 CLSID {6DECC242-87EF-11cf-86B4-444553540000}
>>
>> auto CLSID_DOMDocument60 = Guid!("6DECC242-87EF-11cf-86B4-444553540000");
>> auto iid = IID_IUnknown;
>>
>> void* pUnk;
>> auto hr = CoCreateInstance(&CLSID_DOMDocument60, null, CLSCTX_ALL, &iid, &pUnk);
>> if (FAILED(hr))
>> throw new Exception("Error!");
>>
>> writeln("Hello D-World!");
>> return 0;
>> }
>>
>> Maybe my CLSID's are wrong. Got them from the registry. The exception triggers each time. Even if it worked, I wouldn't know how to use it.
>>
>> I can do this stuff in C# by simply dragging and dropping a dll into the references and it works fine but is a bit slow. I was hoping I could speed things up using D but it seems like COM isn't really supported, despite what several references say.
>
> COM is supported in D. The difference is that C# hides all the plumbing behind nice classes.
>
> You're going to need Photoshop's COM interface to do anything with it. If you don't have a C header that you can translate into D, you could use a tool included in the Windows SDK called OleView. It will peek inside COM libraries and give you the interface definitions.
>
> As to why CoCreateInstance isn't working, make sure you're calling CoInitialize or CoInitializeEx beforehand. If it's still failing, use std.windows.syserror.sysErrorString(hr) to see if it gives you a reason. Otherwise, CLSCTX_ALL might be the culprit - try using CLSCTX_SERVER instead.
Cool. Oleview gives me the idl files. How to convert the idl files to d or possibly c?
Would I just use them in place of IUnknown once I have the interface?
|
June 13, 2016 Re: Accessing COM Objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Incognito | On Monday, 13 June 2016 at 17:38:41 UTC, Incognito wrote:
> Cool. Oleview gives me the idl files. How to convert the idl files to d or possibly c?
>
> Would I just use them in place of IUnknown once I have the interface?
In OleView you can save the IDL file, then run another tool, midl.exe, on the IDL file. That will generate the C headers. But you'd then have to translate that to D by hand.
I have written a tool that takes a COM type library and automatically converts it to a D source file. I could finish it off over the next few days and put the source on GitHub if you're interested.
|
June 13, 2016 Re: Accessing COM Objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to John | On Monday, 13 June 2016 at 19:11:59 UTC, John wrote:
> On Monday, 13 June 2016 at 17:38:41 UTC, Incognito wrote:
>> Cool. Oleview gives me the idl files. How to convert the idl files to d or possibly c?
>>
>> Would I just use them in place of IUnknown once I have the interface?
>
> In OleView you can save the IDL file, then run another tool, midl.exe, on the IDL file. That will generate the C headers. But you'd then have to translate that to D by hand.
>
> I have written a tool that takes a COM type library and automatically converts it to a D source file. I could finish it off over the next few days and put the source on GitHub if you're interested.
That would be great! With it I might be able to put a nice wrapper around Photoshop for use with D. Others mind find it useful too as other programs still use COM.
|
Copyright © 1999-2021 by the D Language Foundation