Re: Mimicking IID_PPV_ARGS

2018-08-30 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/30/18 1:43 AM, Cody Duncan wrote:

On Wednesday, 29 August 2018 at 16:17:13 UTC, Steven Schveighoffer wrote:

On 8/29/18 5:51 AM, Cody Duncan wrote:

 From C++
#define IID_PPV_ARGS(ppType) __uuidof(**(ppType)), 
IID_PPV_ARGS_Helper(ppType)


//ComPtr version
ComPtr debugController;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(
{
 // do stuff
}

//Raw Pointer Version
ID3D12Debug* debugController;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(
{
 // do stuff
}

IID_PPV_ARGS expands into two arguments of types (const IID &, void**).

The first arg expansion uses a compiler intrinsic to look up the GUID 
of the type.


The second arg expansion uses an IID_PPV_ARGS_Helper, a templated 
function that return a void**. This either forwards the address of 
the pointer passed in,
or the result of  ReleaseAndGetAddressOf() from the com object within 
the ComPtr.




Now in D!
Here is my attempt so far, pared down to just enough to compile 
"IID_PPV_ARGS(debugController).expand".


// - uuidtemplate.d -
module uuidtemplate;
import core.sys.windows.com;

mixin( uuid!(IUnknown, "---C000-0046"));
mixin( uuid!(IClassFactory,"0001---C000-0046"));

template uuid(T, const char[] g) {
 const char [] uuid =
 "const IID IID_"~T.stringof~"={ 0x" ~ g[0..8] ~ ",0x" ~ 
g[9..13] ~ ",0x" ~ g[14..18] ~ ",[0x" ~ g[19..21] ~ ",0x" ~ g[21..23] 
~ ",0x" ~ g[24..26] ~ ",0x" ~ g[26..28] ~ ",0x" ~ g[28..30] ~ ",0x" ~ 
g[30..32] ~ ",0x" ~ g[32..34] ~ ",0x" ~ g[34..36] ~ "]};"~

 "template uuidof(T:"~T.stringof~"){"~
 "    const IID uuidof ={ 0x" ~ g[0..8] ~ ",0x" ~ g[9..13] ~ 
",0x" ~ g[14..18] ~ ",[0x" ~ g[19..21] ~ ",0x" ~ g[21..23] ~ ",0x" ~ 
g[24..26] ~ ",0x" ~ g[26..28] ~ ",0x" ~ g[28..30] ~ ",0x" ~ g[30..32] 
~ ",0x" ~ g[32..34] ~ ",0x" ~ g[34..36] ~ "]};"~

 "}";
}

//  - debuginterface.d -
module debuginterface;

import core.sys.windows.com;
import uuidtemplate : uuid; // uuidof

mixin(uuid!(ID3D12Debug, "344488b7-6846-474b-b989-f027448245e0"));
interface ID3D12Debug : IUnknown {
 void EnableDebugLayer();
}

//  - comptr.d -
module comptr;
public import std.typecons;
import core.sys.windows.com;
import uuidtemplate : uuid; // uuidof

mixin template IID_PPV_ARGS()
{
 auto IID_PPV_ARGS(T : ComPtr!U, U)(ref T arg)
 {
 return tuple(!(U), arg.ptrRef());
 }

 auto IID_PPV_ARGS(T)(ref T arg)
 {
 return tuple(!(T), );
 }
}

template ComPtr(T)
{
 struct ComPtr
 {
 protected:
 T _ptr = null;

 public:
 this(ref T inVar)
 {
 _ptr = inVar;
 }

 @property T ptr() { return _ptr; }
 @property T* ptrRef() { return &_ptr; }

 alias ptr this;
 }
}


//  - app.d -
module app;

import core.sys.windows.com;
import comptr;
import debuginterface;
import std.stdio;

// Necessary to mixin since the declaration in comptr.d
// cannot see the uuidof declared by debuginterface.
// When removing the mixin, it always returns the GUID for IUnknown.
mixin IID_PPV_ARGS;

bool D3D12GetDebugInterface(const (GUID)* riid, ID3D12Debug* ppvDebug)
{
 printf("Guid = 
{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}",

 riid.Data1, riid.Data2, riid.Data3,
 riid.Data4[0], riid.Data4[1], riid.Data4[2], riid.Data4[3],
 riid.Data4[4], riid.Data4[5], riid.Data4[6], riid.Data4[7]);

 // output should be: "344488b7-6846-474b-b989-f027448245e0"

 return true;
}

void main()
{
 ComPtr!ID3D12Debug debugController;

 // I want to get rid of the .expand syntax here
 if (D3D12GetDebugInterface(IID_PPV_ARGS(debugController).expand))
 {
 writefln("success!");
 }
}

/// end code

So my goal here is to get the syntax for IID_PPV_ARGS down to looking 
just like a function call.


I'd like to get rid of the .expand call. I haven't figured out a 
better way to express converting the ComPtr input into two outputs 
used as separate arguments into the outer function.


Any ideas?


Unfortunately, D does not allow you to return an alias sequence 
directly. So you have to return a struct, which is going to be 
utilized instead of the alias this'd alias sequence inside the tuple. 
This is why it's necessary for the expand call.


However, it's not much different to accept the struct than it is to 
accept the 2 items in the struct. Why not just modify the function 
D3D12... to accept a struct instead of the 2 parameters? You could 
even overload it, if you still want to call it directly:


bool D3D12GetDebugInterface(Tuple!(const (GUID)*, ID3D12Debug*) param)
{
   return D3D12GetDebugInterface(param.expand);
}

My preference would be to encompass all the logic for pairing the 2 
items together into a specialized struct, not a tuple.





I like the idea of an adapter function, but I'm not a huge fan of the 
prospect to generate adapters for the hundreds of 

Re: Mimicking IID_PPV_ARGS

2018-08-29 Thread Cody Duncan via Digitalmars-d-learn
On Wednesday, 29 August 2018 at 16:17:13 UTC, Steven 
Schveighoffer wrote:

On 8/29/18 5:51 AM, Cody Duncan wrote:

 From C++
#define IID_PPV_ARGS(ppType) __uuidof(**(ppType)), 
IID_PPV_ARGS_Helper(ppType)


//ComPtr version
ComPtr debugController;
if 
(SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(

{
 // do stuff
}

//Raw Pointer Version
ID3D12Debug* debugController;
if 
(SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(

{
 // do stuff
}

IID_PPV_ARGS expands into two arguments of types (const IID &, 
void**).


The first arg expansion uses a compiler intrinsic to look up 
the GUID of the type.


The second arg expansion uses an IID_PPV_ARGS_Helper, a 
templated function that return a void**. This either forwards 
the address of the pointer passed in,
or the result of  ReleaseAndGetAddressOf() from the com object 
within the ComPtr.




Now in D!
Here is my attempt so far, pared down to just enough to 
compile "IID_PPV_ARGS(debugController).expand".


// - uuidtemplate.d -
module uuidtemplate;
import core.sys.windows.com;

mixin( uuid!(IUnknown, 
"---C000-0046"));
mixin( 
uuid!(IClassFactory,"0001---C000-0046"));


template uuid(T, const char[] g) {
 const char [] uuid =
     "const IID IID_"~T.stringof~"={ 0x" ~ g[0..8] ~ ",0x" 
~ g[9..13] ~ ",0x" ~ g[14..18] ~ ",[0x" ~ g[19..21] ~ ",0x" ~ 
g[21..23] ~ ",0x" ~ g[24..26] ~ ",0x" ~ g[26..28] ~ ",0x" ~ 
g[28..30] ~ ",0x" ~ g[30..32] ~ ",0x" ~ g[32..34] ~ ",0x" ~ 
g[34..36] ~ "]};"~

     "template uuidof(T:"~T.stringof~"){"~
     "    const IID uuidof ={ 0x" ~ g[0..8] ~ ",0x" ~ 
g[9..13] ~ ",0x" ~ g[14..18] ~ ",[0x" ~ g[19..21] ~ ",0x" ~ 
g[21..23] ~ ",0x" ~ g[24..26] ~ ",0x" ~ g[26..28] ~ ",0x" ~ 
g[28..30] ~ ",0x" ~ g[30..32] ~ ",0x" ~ g[32..34] ~ ",0x" ~ 
g[34..36] ~ "]};"~

     "}";
}

//  - debuginterface.d -
module debuginterface;

import core.sys.windows.com;
import uuidtemplate : uuid; // uuidof

mixin(uuid!(ID3D12Debug, 
"344488b7-6846-474b-b989-f027448245e0"));

interface ID3D12Debug : IUnknown {
 void EnableDebugLayer();
}

//  - comptr.d -
module comptr;
public import std.typecons;
import core.sys.windows.com;
import uuidtemplate : uuid; // uuidof

mixin template IID_PPV_ARGS()
{
 auto IID_PPV_ARGS(T : ComPtr!U, U)(ref T arg)
 {
     return tuple(!(U), arg.ptrRef());
 }

 auto IID_PPV_ARGS(T)(ref T arg)
 {
     return tuple(!(T), );
 }
}

template ComPtr(T)
{
 struct ComPtr
 {
 protected:
     T _ptr = null;

 public:
     this(ref T inVar)
     {
     _ptr = inVar;
     }

     @property T ptr() { return _ptr; }
     @property T* ptrRef() { return &_ptr; }

     alias ptr this;
 }
}


//  - app.d -
module app;

import core.sys.windows.com;
import comptr;
import debuginterface;
import std.stdio;

// Necessary to mixin since the declaration in comptr.d
// cannot see the uuidof declared by debuginterface.
// When removing the mixin, it always returns the GUID for 
IUnknown.

mixin IID_PPV_ARGS;

bool D3D12GetDebugInterface(const (GUID)* riid, ID3D12Debug* 
ppvDebug)

{
 printf("Guid = 
{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}",

 riid.Data1, riid.Data2, riid.Data3,
 riid.Data4[0], riid.Data4[1], riid.Data4[2], 
riid.Data4[3],
 riid.Data4[4], riid.Data4[5], riid.Data4[6], 
riid.Data4[7]);


 // output should be: 
"344488b7-6846-474b-b989-f027448245e0"


 return true;
}

void main()
{
 ComPtr!ID3D12Debug debugController;

 // I want to get rid of the .expand syntax here
 if 
(D3D12GetDebugInterface(IID_PPV_ARGS(debugController).expand))

 {
     writefln("success!");
 }
}

/// end code

So my goal here is to get the syntax for IID_PPV_ARGS down to 
looking just like a function call.


I'd like to get rid of the .expand call. I haven't figured out 
a better way to express converting the ComPtr input into two 
outputs used as separate arguments into the outer function.


Any ideas?


Unfortunately, D does not allow you to return an alias sequence 
directly. So you have to return a struct, which is going to be 
utilized instead of the alias this'd alias sequence inside the 
tuple. This is why it's necessary for the expand call.


However, it's not much different to accept the struct than it 
is to accept the 2 items in the struct. Why not just modify the 
function D3D12... to accept a struct instead of the 2 
parameters? You could even overload it, if you still want to 
call it directly:


bool D3D12GetDebugInterface(Tuple!(const (GUID)*, ID3D12Debug*) 
param)

{
   return D3D12GetDebugInterface(param.expand);
}

My preference would be to encompass all the logic for pairing 
the 2 items together into a specialized struct, not a tuple.


-Steve



I like the idea of an adapter function, but I'm not a huge fan of 
the prospect to generate adapters for the hundreds of DirectX 

Re: Mimicking IID_PPV_ARGS

2018-08-29 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/29/18 5:51 AM, Cody Duncan wrote:

 From C++
#define IID_PPV_ARGS(ppType) __uuidof(**(ppType)), 
IID_PPV_ARGS_Helper(ppType)


//ComPtr version
ComPtr debugController;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(
{
 // do stuff
}

//Raw Pointer Version
ID3D12Debug* debugController;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(
{
 // do stuff
}

IID_PPV_ARGS expands into two arguments of types (const IID &, void**).

The first arg expansion uses a compiler intrinsic to look up the GUID of 
the type.


The second arg expansion uses an IID_PPV_ARGS_Helper, a templated 
function that return a void**. This either forwards the address of the 
pointer passed in,
or the result of  ReleaseAndGetAddressOf() from the com object within 
the ComPtr.




Now in D!
Here is my attempt so far, pared down to just enough to compile 
"IID_PPV_ARGS(debugController).expand".


// - uuidtemplate.d -
module uuidtemplate;
import core.sys.windows.com;

mixin( uuid!(IUnknown, "---C000-0046"));
mixin( uuid!(IClassFactory,"0001---C000-0046"));

template uuid(T, const char[] g) {
 const char [] uuid =
     "const IID IID_"~T.stringof~"={ 0x" ~ g[0..8] ~ ",0x" ~ 
g[9..13] ~ ",0x" ~ g[14..18] ~ ",[0x" ~ g[19..21] ~ ",0x" ~ g[21..23] ~ 
",0x" ~ g[24..26] ~ ",0x" ~ g[26..28] ~ ",0x" ~ g[28..30] ~ ",0x" ~ 
g[30..32] ~ ",0x" ~ g[32..34] ~ ",0x" ~ g[34..36] ~ "]};"~

     "template uuidof(T:"~T.stringof~"){"~
     "    const IID uuidof ={ 0x" ~ g[0..8] ~ ",0x" ~ g[9..13] ~ 
",0x" ~ g[14..18] ~ ",[0x" ~ g[19..21] ~ ",0x" ~ g[21..23] ~ ",0x" ~ 
g[24..26] ~ ",0x" ~ g[26..28] ~ ",0x" ~ g[28..30] ~ ",0x" ~ g[30..32] ~ 
",0x" ~ g[32..34] ~ ",0x" ~ g[34..36] ~ "]};"~

     "}";
}

//  - debuginterface.d -
module debuginterface;

import core.sys.windows.com;
import uuidtemplate : uuid; // uuidof

mixin(uuid!(ID3D12Debug, "344488b7-6846-474b-b989-f027448245e0"));
interface ID3D12Debug : IUnknown {
 void EnableDebugLayer();
}

//  - comptr.d -
module comptr;
public import std.typecons;
import core.sys.windows.com;
import uuidtemplate : uuid; // uuidof

mixin template IID_PPV_ARGS()
{
 auto IID_PPV_ARGS(T : ComPtr!U, U)(ref T arg)
 {
     return tuple(!(U), arg.ptrRef());
 }

 auto IID_PPV_ARGS(T)(ref T arg)
 {
     return tuple(!(T), );
 }
}

template ComPtr(T)
{
 struct ComPtr
 {
 protected:
     T _ptr = null;

 public:
     this(ref T inVar)
     {
     _ptr = inVar;
     }

     @property T ptr() { return _ptr; }
     @property T* ptrRef() { return &_ptr; }

     alias ptr this;
 }
}


//  - app.d -
module app;

import core.sys.windows.com;
import comptr;
import debuginterface;
import std.stdio;

// Necessary to mixin since the declaration in comptr.d
// cannot see the uuidof declared by debuginterface.
// When removing the mixin, it always returns the GUID for IUnknown.
mixin IID_PPV_ARGS;

bool D3D12GetDebugInterface(const (GUID)* riid, ID3D12Debug* ppvDebug)
{
 printf("Guid = 
{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}",

 riid.Data1, riid.Data2, riid.Data3,
 riid.Data4[0], riid.Data4[1], riid.Data4[2], riid.Data4[3],
 riid.Data4[4], riid.Data4[5], riid.Data4[6], riid.Data4[7]);

 // output should be: "344488b7-6846-474b-b989-f027448245e0"

 return true;
}

void main()
{
 ComPtr!ID3D12Debug debugController;

 // I want to get rid of the .expand syntax here
 if (D3D12GetDebugInterface(IID_PPV_ARGS(debugController).expand))
 {
     writefln("success!");
 }
}

/// end code

So my goal here is to get the syntax for IID_PPV_ARGS down to looking 
just like a function call.


I'd like to get rid of the .expand call. I haven't figured out a better 
way to express converting the ComPtr input into two outputs used as 
separate arguments into the outer function.


Any ideas?


Unfortunately, D does not allow you to return an alias sequence 
directly. So you have to return a struct, which is going to be utilized 
instead of the alias this'd alias sequence inside the tuple. This is why 
it's necessary for the expand call.


However, it's not much different to accept the struct than it is to 
accept the 2 items in the struct. Why not just modify the function 
D3D12... to accept a struct instead of the 2 parameters? You could even 
overload it, if you still want to call it directly:


bool D3D12GetDebugInterface(Tuple!(const (GUID)*, ID3D12Debug*) param)
{
   return D3D12GetDebugInterface(param.expand);
}

My preference would be to encompass all the logic for pairing the 2 
items together into a specialized struct, not a tuple.


-Steve


Mimicking IID_PPV_ARGS

2018-08-29 Thread Cody Duncan via Digitalmars-d-learn

From C++
#define IID_PPV_ARGS(ppType) __uuidof(**(ppType)), 
IID_PPV_ARGS_Helper(ppType)


//ComPtr version
ComPtr debugController;
if 
(SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(

{
// do stuff
}

//Raw Pointer Version
ID3D12Debug* debugController;
if 
(SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(

{
// do stuff
}

IID_PPV_ARGS expands into two arguments of types (const IID &, 
void**).


The first arg expansion uses a compiler intrinsic to look up the 
GUID of the type.


The second arg expansion uses an IID_PPV_ARGS_Helper, a templated 
function that return a void**. This either forwards the address 
of the pointer passed in,
or the result of  ReleaseAndGetAddressOf() from the com object 
within the ComPtr.




Now in D!
Here is my attempt so far, pared down to just enough to compile 
"IID_PPV_ARGS(debugController).expand".


// - uuidtemplate.d -
module uuidtemplate;
import core.sys.windows.com;

mixin( uuid!(IUnknown, "---C000-0046"));
mixin( 
uuid!(IClassFactory,"0001---C000-0046"));


template uuid(T, const char[] g) {
const char [] uuid =
		"const IID IID_"~T.stringof~"={ 0x" ~ g[0..8] ~ ",0x" ~ 
g[9..13] ~ ",0x" ~ g[14..18] ~ ",[0x" ~ g[19..21] ~ ",0x" ~ 
g[21..23] ~ ",0x" ~ g[24..26] ~ ",0x" ~ g[26..28] ~ ",0x" ~ 
g[28..30] ~ ",0x" ~ g[30..32] ~ ",0x" ~ g[32..34] ~ ",0x" ~ 
g[34..36] ~ "]};"~

"template uuidof(T:"~T.stringof~"){"~
		"	const IID uuidof ={ 0x" ~ g[0..8] ~ ",0x" ~ g[9..13] ~ ",0x" 
~ g[14..18] ~ ",[0x" ~ g[19..21] ~ ",0x" ~ g[21..23] ~ ",0x" ~ 
g[24..26] ~ ",0x" ~ g[26..28] ~ ",0x" ~ g[28..30] ~ ",0x" ~ 
g[30..32] ~ ",0x" ~ g[32..34] ~ ",0x" ~ g[34..36] ~ "]};"~

"}";
}

//  - debuginterface.d -
module debuginterface;

import core.sys.windows.com;
import uuidtemplate : uuid; // uuidof

mixin(uuid!(ID3D12Debug, "344488b7-6846-474b-b989-f027448245e0"));
interface ID3D12Debug : IUnknown {
void EnableDebugLayer();
}

//  - comptr.d -
module comptr;
public import std.typecons;
import core.sys.windows.com;
import uuidtemplate : uuid; // uuidof

mixin template IID_PPV_ARGS()
{
auto IID_PPV_ARGS(T : ComPtr!U, U)(ref T arg)
{
return tuple(!(U), arg.ptrRef());
}

auto IID_PPV_ARGS(T)(ref T arg)
{
return tuple(!(T), );
}
}

template ComPtr(T)
{
struct ComPtr
{
protected:
T _ptr = null;

public:
this(ref T inVar)
{
_ptr = inVar;
}

@property T ptr() { return _ptr; }
@property T* ptrRef() { return &_ptr; }

alias ptr this;
}
}


//  - app.d -
module app;

import core.sys.windows.com;
import comptr;
import debuginterface;
import std.stdio;

// Necessary to mixin since the declaration in comptr.d
// cannot see the uuidof declared by debuginterface.
// When removing the mixin, it always returns the GUID for 
IUnknown.

mixin IID_PPV_ARGS;

bool D3D12GetDebugInterface(const (GUID)* riid, ID3D12Debug* 
ppvDebug)

{
	printf("Guid = 
{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}",

riid.Data1, riid.Data2, riid.Data3,
riid.Data4[0], riid.Data4[1], riid.Data4[2], riid.Data4[3],
riid.Data4[4], riid.Data4[5], riid.Data4[6], riid.Data4[7]);

// output should be: "344488b7-6846-474b-b989-f027448245e0"

return true;
}

void main()
{
ComPtr!ID3D12Debug debugController;

// I want to get rid of the .expand syntax here
if (D3D12GetDebugInterface(IID_PPV_ARGS(debugController).expand))
{
writefln("success!");
}
}

/// end code

So my goal here is to get the syntax for IID_PPV_ARGS down to 
looking just like a function call.


I'd like to get rid of the .expand call. I haven't figured out a 
better way to express converting the ComPtr input into two 
outputs used as separate arguments into the outer function.


Any ideas?