mirror of https://github.com/adamdruppe/arsd.git
more stuff
This commit is contained in:
parent
91dad75e5f
commit
cc1160505b
80
com.d
80
com.d
|
@ -45,15 +45,28 @@
|
|||
//writeln(obj.opDispatch!("test", int)());
|
||||
}
|
||||
---
|
||||
|
||||
I'll show a COM server example later. It is cool to call D objects
|
||||
from JScript and such.
|
||||
+/
|
||||
module arsd.com;
|
||||
|
||||
// for arrays to/from IDispatch use SAFEARRAY
|
||||
// see https://stackoverflow.com/questions/295067/passing-an-array-using-com
|
||||
|
||||
// for exceptions
|
||||
// see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/705fb797-2175-4a90-b5a3-3918024b10b8
|
||||
// see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/0c0bcf55-277e-4120-b5dc-f6115fc8dc38
|
||||
|
||||
/+
|
||||
see: program\comtest.d on the laptop.
|
||||
see: program\cs\comtest.d on the laptop.
|
||||
|
||||
as administrator: from program\cs
|
||||
c:\Windows\Microsoft.NEt\Framework64\v4.0.30319\regasm.exe /regfile /codebase test.dll
|
||||
|
||||
note: use the 64 bit register for 64 bit programs (Framework64)
|
||||
use 32 for 32 bit program (\Framework\)
|
||||
|
||||
sn -k key.snk
|
||||
program\cs\makefile
|
||||
|
||||
|
@ -69,6 +82,16 @@ module arsd.com;
|
|||
and then fully dynamic can be done with opDispatch for teh lulz.
|
||||
+/
|
||||
|
||||
/+
|
||||
createComObject returns the wrapped one
|
||||
wrapping can go dynamic if it is wrapping IDispatch
|
||||
some other IUnknown gets minimal wrapping (Translate formats)
|
||||
all wrappers can return lower level stuff on demand. like LL!string maybe is actually an RAII BSTR.
|
||||
|
||||
i also want variant to jsvar and stuff like that.
|
||||
createRawComObject returns the IUnknown raw one
|
||||
+/
|
||||
|
||||
import core.sys.windows.windows;
|
||||
import core.sys.windows.com;
|
||||
import core.sys.windows.oaidl;
|
||||
|
@ -167,7 +190,7 @@ template Dify(T) {
|
|||
import std.traits;
|
||||
|
||||
///
|
||||
struct ComClient(DVersion, ComVersion) {
|
||||
struct ComClient(DVersion, ComVersion = IDispatch) {
|
||||
ComVersion innerComObject_;
|
||||
this(ComVersion t) {
|
||||
this.innerComObject_ = t;
|
||||
|
@ -209,7 +232,8 @@ struct ComClient(DVersion, ComVersion) {
|
|||
static if(args.length) {
|
||||
VARIANT[args.length] vargs;
|
||||
foreach(idx, arg; args) {
|
||||
vargs[idx] = toComVariant(arg);
|
||||
// lol it is put in backwards way to explain MSFT
|
||||
vargs[$ - 1 - idx] = toComVariant(arg);
|
||||
}
|
||||
|
||||
disp_params.rgvarg = vargs.ptr;
|
||||
|
@ -217,16 +241,47 @@ struct ComClient(DVersion, ComVersion) {
|
|||
}
|
||||
|
||||
VARIANT result;
|
||||
EXCEPINFO einfo;
|
||||
uint argError;
|
||||
|
||||
ComCheck(innerComObject_.Invoke(
|
||||
//ComCheck(innerComObject_.Invoke(
|
||||
auto hr =innerComObject_.Invoke(
|
||||
dispid,
|
||||
&GUID_NULL, LOCALE_SYSTEM_DEFAULT, // whatever
|
||||
DISPATCH_METHOD,
|
||||
&disp_params,
|
||||
&result,
|
||||
null, // exception info
|
||||
null // arg error
|
||||
), "Invoke");
|
||||
&einfo, // exception info
|
||||
&argError // arg error
|
||||
);//, "Invoke");
|
||||
|
||||
import std.conv;
|
||||
if(FAILED(hr)) {
|
||||
if(hr == DISP_E_EXCEPTION) {
|
||||
auto code = einfo.scode ? einfo.scode : einfo.wCode;
|
||||
string source;
|
||||
string description;
|
||||
if(einfo.bstrSource) {
|
||||
// this is really a wchar[] but it needs to be freed so....
|
||||
source = einfo.bstrSource[0 .. SysStringLen(einfo.bstrSource)].to!string;
|
||||
SysFreeString(einfo.bstrSource);
|
||||
}
|
||||
if(einfo.bstrDescription) {
|
||||
description = einfo.bstrDescription[0 .. SysStringLen(einfo.bstrDescription)].to!string;
|
||||
SysFreeString(einfo.bstrDescription);
|
||||
}
|
||||
if(einfo.bstrHelpFile) {
|
||||
// FIXME: we could prolly use this too
|
||||
SysFreeString(einfo.bstrHelpFile);
|
||||
// and dwHelpContext
|
||||
}
|
||||
|
||||
throw new ComException(code, description ~ " (from com source " ~ source ~ ")");
|
||||
|
||||
} else {
|
||||
throw new ComException(hr, "Call failed");
|
||||
}
|
||||
}
|
||||
|
||||
return getFromVariant!(typeof(return))(result);
|
||||
} else {
|
||||
|
@ -338,6 +393,9 @@ T getFromVariant(T)(VARIANT arg) {
|
|||
static if(is(T == int)) {
|
||||
if(arg.vt == 3)
|
||||
return arg.intVal;
|
||||
} else static if(is(T == bool)) {
|
||||
if(arg.vt == 11)
|
||||
return arg.boolVal ? true : false;
|
||||
} else static if(is(T == string)) {
|
||||
if(arg.vt == 8) {
|
||||
auto str = arg.bstrVal;
|
||||
|
@ -346,6 +404,12 @@ T getFromVariant(T)(VARIANT arg) {
|
|||
} else static if(is(T == IDispatch)) {
|
||||
if(arg.vt == 9)
|
||||
return arg.pdispVal;
|
||||
} else static if(is(T : IUnknown)) {
|
||||
// if(arg.vt == 13)
|
||||
static assert(0);
|
||||
} else static if(is(T == ComClient!(D, I), D, I)) {
|
||||
if(arg.vt == 9)
|
||||
return ComClient!(D, I)(arg.pdispVal);
|
||||
}
|
||||
throw new Exception("Type mismatch, needed "~ T.stringof ~"got " ~ to!string(arg.vt));
|
||||
assert(0);
|
||||
|
@ -432,7 +496,7 @@ mixin template IDispatchImpl() {
|
|||
} catch(Throwable e) {
|
||||
// FIXME: fill in the exception info
|
||||
if(except !is null) {
|
||||
except.wCode = 1;
|
||||
except.sCode = 1;
|
||||
import std.utf;
|
||||
except.bstrDescription = SysAllocString(toUTFz!(wchar*)(e.toString()));
|
||||
except.bstrSource = SysAllocString("amazing"w.ptr);
|
||||
|
|
Loading…
Reference in New Issue