Re: C++ interface vs D and com

2016-07-14 Thread Kagamin via Digitalmars-d-learn

On Wednesday, 13 July 2016 at 21:27:29 UTC, Adam Sansier wrote:
Yes! your right, If you were only around to tell me that in the 
first place! ;) Now we know. Again, as I said before, the 
problem is informational.


We know it only after you posted links to threads with relevant 
info. You knew the problem is informational yet decided to 
conceal the relevant information and you knew it will result in a 
problem, so you consciously created that problem, it's not the 
world to blame for that. People in the treads you linked don't do 
such things, they easily see the details, provide relevant info, 
even full declaration of the interface, you don't do that, it was 
your decision to create that problem, it's not the world to blame 
for that. COM is documented, the world suggests to read docs 
before you get to anything or when you're in a trouble, you don't 
do that, and you know it leads to problems, and it's your 
decision to ask for those problems, that's your attitude - to 
create problems you suffer from, nobody else does that.


I've created a big enough stink about it that anyone in the 
future having similar issues might be able to resolve them much 
quicker.


You only created lots of whining providing zero information about 
what's going on, that zero information won't help anyone.


Re: C++ interface vs D and com

2016-07-13 Thread Mike Parker via Digitalmars-d-learn

On Wednesday, 13 July 2016 at 21:27:29 UTC, Adam Sansier wrote:



Yes! your right, If you were only around to tell me that in the 
first place! ;) Now we know. Again, as I said before, the 
problem is informational. Maybe because come works 99% of the 
time doesn't help us in the 1% if some think 99%=100%(that new 
math shit that's causing so many problems). I've created a big 
enough stink about it that anyone in the future having similar 
issues might be able to resolve them much quicker.



This demonstrates the importance of showing example code. 
Everyone who tried to help you in this thread was going on the 
assumption that you were using a library that does not deviate 
from standard practice. Personally, I had no idea that there were 
"COM" libraries that do that. When I did ask for example code, 
you still didn't post anything relevant, i.e. something that 
shows your interface declarations or how you were obtaining the 
COM pointer.


Generally, you want to give as much info as possible with these 
sorts of problems, including compiler, command line options, 
error messages, and anything you can think of that is relevant. 
That you were using ASIO should have been in your very first 
post. Please keep that in mind the next time you have an issue. 
It may save you a lot of grief.


Re: C++ interface vs D and com

2016-07-13 Thread Adam Sansier via Digitalmars-d-learn

On Wednesday, 13 July 2016 at 20:47:21 UTC, John wrote:

On Wednesday, 13 July 2016 at 20:28:40 UTC, Adam Sansier wrote:

On Wednesday, 13 July 2016 at 19:22:44 UTC, Kagamin wrote:
On Wednesday, 13 July 2016 at 16:48:53 UTC, Adam Sansier 
wrote:

There's a lot of misinformation on the net.


Nope, it's just you. COM support in D and in general works 
fine for everyone else.


For anyone else having similar problems please ignore. COM 
doesn't work perfectly regardless of what some nobody says and 
I'm not the only one having problems. There are others and a 
search shows this.


http://forum.dlang.org/thread/iovu2e$2d3d$1...@digitalmars.com

I notice you are the last one to say "COM uses stdcall 
convention. Everything else is not COM." Spreading your lies 
and disinformation. People like you are a source of problems, 
not a solution. Please learn that you don't know everything 
and your generalization about how everything works is simply 
wrong.


http://www.digitalmars.com/d/archives/digitalmars/D/learn/thiscall_calling_convention_4943.html

Regardless of why the problems exist, or if they are subtle or 
only in certain scenarios, they exist and some imbecile 
claiming they don't just makes more trouble for those trying 
to solve their problems.


If you don't like my attitude, stop acting like the world is 
perfect and when someone has a problem that it just might be 
legitimate. If you don't actually feel like helping, simply 
don't reply, it's that easy.


The problem is that ASIO deviates from the standard way of 
implementing COM. Other languages like Delphi expect COM to use 
stdcall too, so the problem is not unique to D. Putting 
"extern(C++):" before the interface method declarations should 
allow it to work...


interface IASIO : IUnknown {
  extern(C++):
  HRESULT SomeMethod();
}


NO! If you do that then it's not COM! Put extern(Windows)! It's 
the only way it can work!


Yes! your right, If you were only around to tell me that in the 
first place! ;) Now we know. Again, as I said before, the problem 
is informational. Maybe because come works 99% of the time 
doesn't help us in the 1% if some think 99%=100%(that new math 
shit that's causing so many problems). I've created a big enough 
stink about it that anyone in the future having similar issues 
might be able to resolve them much quicker.


Thanks.






Re: C++ interface vs D and com

2016-07-13 Thread John via Digitalmars-d-learn

On Wednesday, 13 July 2016 at 20:28:40 UTC, Adam Sansier wrote:

On Wednesday, 13 July 2016 at 19:22:44 UTC, Kagamin wrote:

On Wednesday, 13 July 2016 at 16:48:53 UTC, Adam Sansier wrote:

There's a lot of misinformation on the net.


Nope, it's just you. COM support in D and in general works 
fine for everyone else.


For anyone else having similar problems please ignore. COM 
doesn't work perfectly regardless of what some nobody says and 
I'm not the only one having problems. There are others and a 
search shows this.


http://forum.dlang.org/thread/iovu2e$2d3d$1...@digitalmars.com

I notice you are the last one to say "COM uses stdcall 
convention. Everything else is not COM." Spreading your lies 
and disinformation. People like you are a source of problems, 
not a solution. Please learn that you don't know everything and 
your generalization about how everything works is simply wrong.


http://www.digitalmars.com/d/archives/digitalmars/D/learn/thiscall_calling_convention_4943.html

Regardless of why the problems exist, or if they are subtle or 
only in certain scenarios, they exist and some imbecile 
claiming they don't just makes more trouble for those trying to 
solve their problems.


If you don't like my attitude, stop acting like the world is 
perfect and when someone has a problem that it just might be 
legitimate. If you don't actually feel like helping, simply 
don't reply, it's that easy.


The problem is that ASIO deviates from the standard way of 
implementing COM. Other languages like Delphi expect COM to use 
stdcall too, so the problem is not unique to D. Putting 
"extern(C++):" before the interface method declarations should 
allow it to work...


interface IASIO : IUnknown {
  extern(C++):
  HRESULT SomeMethod();
}


Re: C++ interface vs D and com

2016-07-13 Thread Adam Sansier via Digitalmars-d-learn

On Wednesday, 13 July 2016 at 20:02:50 UTC, Jesse Phillips wrote:

On Wednesday, 13 July 2016 at 02:41:22 UTC, Adam Sansier wrote:
If you can convince me to try it out, I might... but doing com 
isn't my primary goal here and I seem to have finished up what 
I was trying to achieve(my use case is probably relatively 
simple though). Last thing I want to do is get bogged down in 
this stuff, which feels clumsy and not well documented(Both 
the D and C sides)


Juno is definitely of more value if you're trying to access 
standard Windows COM objects, that way you don't have to write 
the interface definitions yourself.


You'd mentioned that you got it work with a hack and there 
should be a better way, Juno might be that better way.


It looks to me like your extern(C++) is needed because you're 
trying to shove the pointer from coCreateInstance into a D 
class. With COM you don't work with concrete classes, only 
interfaces. Code below is not tested and only from limited 
knowledge.


IMYCASIO cASIO : IUnknown
{
void func1(char *name);
void func2(int);
}

//...
IMYCASIO obj;
CoCreateInstance(..., cast(void**) );

obj.func1("me");

The only other thing I can think is, if you are obtaining an 
object that defines static methods, those aren't supported by 
COM. COM only works on virtual functions and you're probably 
just hacking memory address space to get at those functions.


But juno wouldn't work with this then? Regardless if the "COM" 
interface I'm using is truly com as defined by some yet unknown 
standard, it is what I have to work with.


I was able to simply the code. I required marking only those 
functions of the interface as extern(C++), everything else is 
normal and simple. I was able to simply cast the ptr to the 
interface and it worked. The thing I tried in the first 5 mins 
that didn't, probably because I used extern(Windows) like some 
fools say *HAVE& to be used which wasted 2 days of my life(ok, 
only a few hours each day but still ;) chasing that rabbit, 
actually did work.


So, the point of this thread is simply to state for those in the 
future that such discrepancies do exist and are hard to figure 
out because there is little info on them.


This already thwarted one person:

http://forum.dlang.org/thread/iovu2e$2d3d$1...@digitalmars.com

So this is a 10 year problem: 2006-2011-2016. Funny how it 
happens in 5 year increments. Was Kagamin in on it? Does he have 
some vested interest in people not getting this stuff to work? 
Luckily I don't listen to fools, and luckily extern(C++) was 
implemented since then and we now have a solution.















Re: C++ interface vs D and com

2016-07-13 Thread Adam Sansier via Digitalmars-d-learn

On Wednesday, 13 July 2016 at 19:22:44 UTC, Kagamin wrote:

On Wednesday, 13 July 2016 at 16:48:53 UTC, Adam Sansier wrote:

There's a lot of misinformation on the net.


Nope, it's just you. COM support in D and in general works fine 
for everyone else.


For anyone else having similar problems please ignore. COM 
doesn't work perfectly regardless of what some nobody says and 
I'm not the only one having problems. There are others and a 
search shows this.


http://forum.dlang.org/thread/iovu2e$2d3d$1...@digitalmars.com

I notice you are the last one to say "COM uses stdcall 
convention. Everything else is not COM." Spreading your lies and 
disinformation. People like you are a source of problems, not a 
solution. Please learn that you don't know everything and your 
generalization about how everything works is simply wrong.


http://www.digitalmars.com/d/archives/digitalmars/D/learn/thiscall_calling_convention_4943.html

Regardless of why the problems exist, or if they are subtle or 
only in certain scenarios, they exist and some imbecile claiming 
they don't just makes more trouble for those trying to solve 
their problems.


If you don't like my attitude, stop acting like the world is 
perfect and when someone has a problem that it just might be 
legitimate. If you don't actually feel like helping, simply don't 
reply, it's that easy.







Re: C++ interface vs D and com

2016-07-13 Thread Jesse Phillips via Digitalmars-d-learn

On Wednesday, 13 July 2016 at 02:41:22 UTC, Adam Sansier wrote:
If you can convince me to try it out, I might... but doing com 
isn't my primary goal here and I seem to have finished up what 
I was trying to achieve(my use case is probably relatively 
simple though). Last thing I want to do is get bogged down in 
this stuff, which feels clumsy and not well documented(Both the 
D and C sides)


Juno is definitely of more value if you're trying to access 
standard Windows COM objects, that way you don't have to write 
the interface definitions yourself.


You'd mentioned that you got it work with a hack and there should 
be a better way, Juno might be that better way.


It looks to me like your extern(C++) is needed because you're 
trying to shove the pointer from coCreateInstance into a D class. 
With COM you don't work with concrete classes, only interfaces. 
Code below is not tested and only from limited knowledge.


IMYCASIO cASIO : IUnknown
{
void func1(char *name);
void func2(int);
}

//...
IMYCASIO obj;
CoCreateInstance(..., cast(void**) );

obj.func1("me");

The only other thing I can think is, if you are obtaining an 
object that defines static methods, those aren't supported by 
COM. COM only works on virtual functions and you're probably just 
hacking memory address space to get at those functions.


Re: C++ interface vs D and com

2016-07-13 Thread Kagamin via Digitalmars-d-learn

On Wednesday, 13 July 2016 at 16:48:53 UTC, Adam Sansier wrote:

There's a lot of misinformation on the net.


Nope, it's just you. COM support in D and in general works fine 
for everyone else.


Re: C++ interface vs D and com

2016-07-13 Thread Adam Sansier via Digitalmars-d-learn

On Wednesday, 13 July 2016 at 08:34:55 UTC, John wrote:

On Wednesday, 13 July 2016 at 07:31:57 UTC, Adam Sansier wrote:

void** ptr = null;  
auto res = CoCreateInstance(_ID, cast(IUnknown)null, 
CLSCTX_INPROC_SERVER, _ID, cast(void**));


How are you casting your "ptr" variable (which BTW should be 
just void* or usually IUnknown) to your interface? A common 
mistake if you're used to C++ is using cast(ISomeInterface*)ptr 
- which would cause access violations - instead of 
cast(ISomeInterface)ptr.



No, I figured that stuff out about the first 5 mins I started 
this 3 day journey.


This is the problem, and I believe the solution:

The COM interface I'm using does not use this in the code and 
either is "static" no this passed or simply ignores it. I know in 
some cases when I would try certain things my arguments to them 
would not be correct(pass a char* to get data and get crap back 
or crash randomly).


IUnknown requires one to pass the interface as a this.

The mismatch between the two created most of the havoc as I 
wrongfully assumed they were all the same and, as typical with 
computers, the behavior was not consistent and sometimes would 
work in some ways and other times wouldn't.


Regardless, to solve the problem, I believe(No crashes, don't 
know if the references are truly handled properly, I have to do 
this:



extern (C++) class cASIO
{
extern (C++)
{
int QueryInterface(void*, const(GUID)* riid, void** 
pvObject)
{
return 0;
}
uint AddRef(void*)
{
return 0;
}
uint Release(void*)
{
return 0;
}
}
extern(C++)
{
void func1(char *name) { }
void func2(int) { }
...
}
}

extern(C++) doesn't pass this or passes it in ECX(Not sure which 
yet, I think it doesn't pass this from what I recall about the 
disassembly).


I then simply manually pass the interface ptr created by 
CoCreateInstance to Release.


Of course, if I could cast the interface ptr directly to a type 
with the interface and it all work, then D should handle that 
stuff behind the scenes. I tried that initially and it might have 
worked or half worked or something.  I will go back and try again 
knowing what I know now and try to keep everything correct.


So, for those that run into these COM problems in the future:

1. Make sure the linkage is 100% correct per function. IUnknown 
uses extern(Windows) but must be passed the correct this or it 
will not work well. This can be emulated by marking them 
extern(C++) and passing the expected this as first parameter.


The actual interface may not have the same linkage as IUnknown. 
If the 0 parameter functions are working but non-zero parameter 
functions are not behaving correctly then is a linkage issue. 
They should be marked extern(C++) as this gives more control over 
what is passed. Passing the correct this as the first parameter 
will either work or not, if not, either the function expects it 
in ECX or it is some type of static like function. This can be 
difficult to know if the function itself doesn't even use this 
internally.


One can debug these things and see the vtable in memory and all 
the function addresses and be sure the addresses are linking up, 
but one can't see the parameter passing as easily. If your sure 
the function addresses are correct and your not calling the wrong 
addresses, then the problem is a linkage issue.


2. The interface ptr returned by COM should be able to be 
mappable to a *COM* interface pointer in D. A normal interface 
differs by a COM interface in D the vtable is offset by a ptr. In 
this case, your calls may work or not depending on the design but 
something will eventually not work causing grief. We have no idea 
how to mark an interface as COM in D... someone once said through 
the grapevine that it does this if it inherits IUnknown. I 
believe that marking it extern(C++) works.


3. There are a lot of pitfalls here because of the way the 
different modifiers work. Some combinations may work when they 
really don't... Trial and error is a real pain. Making sure the 
vtable is correctly being used and then knowing the linkage of 
the interface functions should get one at least 50% there.  This 
assumes different functions in the difference don't use different 
linkage... which may create even more havoc. There's a lot of 
misinformation on the net. Just because someone got some code to 
work in their specific case doesn't mean it is the correct way to 
do it for your case.







Re: C++ interface vs D and com

2016-07-13 Thread Kagamin via Digitalmars-d-learn

On Wednesday, 13 July 2016 at 07:31:57 UTC, Adam Sansier wrote:

void** ptr = null;  
auto res = CoCreateInstance(_ID, cast(IUnknown)null, 
CLSCTX_INPROC_SERVER, _ID, cast(void**));


See the example above.

IUnknown ptr = null;
auto res = CoCreateInstance(, null,
CLSCTX_INPROC_SERVER, , cast(void**));
if(SUCCEEDED(res))ptr.Release();

Are you sure CLSID matches IID in your case?


Re: C++ interface vs D and com

2016-07-13 Thread John via Digitalmars-d-learn

On Wednesday, 13 July 2016 at 07:31:57 UTC, Adam Sansier wrote:

void** ptr = null;  
auto res = CoCreateInstance(_ID, cast(IUnknown)null, 
CLSCTX_INPROC_SERVER, _ID, cast(void**));


How are you casting your "ptr" variable (which BTW should be just 
void* or usually IUnknown) to your interface? A common mistake if 
you're used to C++ is using cast(ISomeInterface*)ptr - which 
would cause access violations - instead of 
cast(ISomeInterface)ptr.


Re: C++ interface vs D and com

2016-07-13 Thread Adam Sansier via Digitalmars-d-learn

On Wednesday, 13 July 2016 at 06:44:36 UTC, Adam Sansier wrote:

On Wednesday, 13 July 2016 at 03:38:03 UTC, Mike Parker wrote:

On Wednesday, 13 July 2016 at 02:49:54 UTC, Adam Sansier wrote:

On Wednesday, 13 July 2016 at 02:34:14 UTC, Mike Parker wrote:


What happens when you declare an interface that extends from 
IUnknown (and not extern(C++)), then cast the pointer 
returned from the COM API? It should just work without 
needing to muck around with the vtable.


That was what I tried first, It didn't work. I don't know 
what the problem though. I either get an access violation or 
the functions don't do anything.


Perhaps you forgot to call CoInitialize{Ex}?


Nope...





I think it's more complex because without extern(C++) the 
vtable is in a different place than expected(it's offset by 
1), so simple casting does not work.


"A COM interface differs from a regular interface in that 
there is no object.Interface entry in vtbl[0]; the entries 
vtbl[0..$] are all the virtual function pointers, in the 
order that they were declared. This matches the COM object 
layout used by Windows.


A C++ interface differs from a regular interface in that it 
matches the layout of a C++ class using single inheritance on 
the target machine. "


You don't need extern(C++) for COM interfaces. There are 
several declared in the Windows bindings that each inherit 
from IUnknown and there's no extern(C++) in sight (they 
existed long before C++ support did). Here's a working example 
using one of them, IShellLinkW, declared in 
core.sys.windows.shlobj.


```
import core.sys.windows.windows,
   core.sys.windows.shlobj,
   core.sys.windows.com;

pragma(lib, "Ole32");

void main()
{
IShellLinkW iface;
auto shellLinkCLSID = CLSID_ShellLink;
auto shellLinkIID = IID_IShellLinkW;

CoInitialize(null);
scope(exit)CoUninitialize();

auto hr = CoCreateInstance(
,
null,
CLSCTX_INPROC_SERVER,
,
cast(void**)
);
if(SUCCEEDED(hr)) {
import std.stdio : writeln;
writeln("Got it!");
iface.Release();
}
else throw new Exception("Failed to create IShellLink 
instance");

}
```

There's a minor annoyance here in that the IID constants are 
all declared in the Windows bindings as manifest constants, 
which is normally the smart thing to do with constants. 
However, they're intended to be used as lvalues with the COM 
API, so I had to save them off in local variables in order to 
take their addresses. You can do whatever you want with your 
own declarations, of course.


You don't have to beleive me, but if I don't mark the methods 
extern(C++), then only 0 arg methods work.


In fact, Release does not work unless I mark it extern (C++).

So, while you may think it should work one way, and maybe it 
does for you in some case, it doesn't for me and has given me 
quite an amount of grief.


Regardless of what you think, I can prove that the code won't 
work when it is marked extern(Windows) and works when it is 
marked extern (C++)... so what you should be asking yourself is 
why it is doing that rather than assuming I'm making it up or 
doing something wrong.


Ok, this is the thing.

In C++ I can do

auto p = *((size_t**)*ptr) + 4;
typedef size_t(__stdcall *fp)(char*);
auto f = (fp)*p;
res = f(n);

to call the 4th function that accepts a char. I can do that for 
all the functions > 2.


If I call 0 through 2 I get errors, that is from the IUnknown 
interface.


It seems the interface I'm using is built up of static 
functions... functions that don't accept a this. Hence they work 
and extern(C++) works for them, which I guess doesn't pass this.


Because of the hacked vtble stuff, the class used is not the 
original vtbl which is required for IUnknown.


Hence, they crash because they either get no this or the wrong 
this.


e.g.,
// Release the interface
auto p = *((size_t**)*ptr) + 2;
typedef size_t(__stdcall *fp)(void*);
auto f = (fp)*p;
res = f(ptr);


I'm not entirely sure if all this is correct but the C++ code 
shows that I don't pass a "this" to the interface functions and 
it works(if it's passed in ECX and they simply don't use it or if 
they are "static" or whatever is going on)... not sure which. 
OTOH, I have to pass something to Release to get it not to crash.


So, any ideas?

void** ptr = null;  
auto res = CoCreateInstance(_ID, cast(IUnknown)null, 
CLSCTX_INPROC_SERVER, _ID, cast(void**));


I could check to see if addref and release are working if I could 
get the number of references. Is this possible? A quick search 
doesn't bring up anything.



To sum up this confusion:

1. Are the working interface functions I'm calling "static"(no 
this)? Is that possible? extern(Windows) breaks the code and 
extern(C++) works. I can call them with a C++ function 

Re: C++ interface vs D and com

2016-07-13 Thread Mike Parker via Digitalmars-d-learn

On Wednesday, 13 July 2016 at 06:44:36 UTC, Adam Sansier wrote:

Regardless of what you think, I can prove that the code won't 
work when it is marked extern(Windows) and works when it is 
marked extern (C++)... so what you should be asking yourself is 
why it is doing that rather than assuming I'm making it up or 
doing something wrong.


I don't have your code in front of me, nor do I have your system 
configuration, and can only go on what I know from my own 
experience. The example I posted works for me. In the past, I 
have successfully used DirectX bindings with D that were not 
marked extern(C++). So I *know* that it does work as intended, at 
least the times I've tried it. That's *my* experience. If it 
isn't working for you, then there must be a reason. I'm not here 
to challenge your story or to accuse you of making things up. I'm 
trying to help you get to the bottom of your problem, i.e. I *am* 
asking myself why you are having these issues.


So you say the sample code doesn't work for you. Fine. That's one 
of the reasons I posted it, so we can establish if it does or 
does not. It would help even more if you could post a minimal 
example of your own code that other people can attempt to 
compile, run and/or debug. Otherwise, the only thing anyone *can* 
do is make guesses and assumptions, and then we get nowhere.


Re: C++ interface vs D and com

2016-07-13 Thread Adam Sansier via Digitalmars-d-learn

On Wednesday, 13 July 2016 at 03:38:03 UTC, Mike Parker wrote:

On Wednesday, 13 July 2016 at 02:49:54 UTC, Adam Sansier wrote:

On Wednesday, 13 July 2016 at 02:34:14 UTC, Mike Parker wrote:


What happens when you declare an interface that extends from 
IUnknown (and not extern(C++)), then cast the pointer 
returned from the COM API? It should just work without 
needing to muck around with the vtable.


That was what I tried first, It didn't work. I don't know what 
the problem though. I either get an access violation or the 
functions don't do anything.


Perhaps you forgot to call CoInitialize{Ex}?


Nope...





I think it's more complex because without extern(C++) the 
vtable is in a different place than expected(it's offset by 
1), so simple casting does not work.


"A COM interface differs from a regular interface in that 
there is no object.Interface entry in vtbl[0]; the entries 
vtbl[0..$] are all the virtual function pointers, in the order 
that they were declared. This matches the COM object layout 
used by Windows.


A C++ interface differs from a regular interface in that it 
matches the layout of a C++ class using single inheritance on 
the target machine. "


You don't need extern(C++) for COM interfaces. There are 
several declared in the Windows bindings that each inherit from 
IUnknown and there's no extern(C++) in sight (they existed long 
before C++ support did). Here's a working example using one of 
them, IShellLinkW, declared in core.sys.windows.shlobj.


```
import core.sys.windows.windows,
   core.sys.windows.shlobj,
   core.sys.windows.com;

pragma(lib, "Ole32");

void main()
{
IShellLinkW iface;
auto shellLinkCLSID = CLSID_ShellLink;
auto shellLinkIID = IID_IShellLinkW;

CoInitialize(null);
scope(exit)CoUninitialize();

auto hr = CoCreateInstance(
,
null,
CLSCTX_INPROC_SERVER,
,
cast(void**)
);
if(SUCCEEDED(hr)) {
import std.stdio : writeln;
writeln("Got it!");
iface.Release();
}
else throw new Exception("Failed to create IShellLink 
instance");

}
```

There's a minor annoyance here in that the IID constants are 
all declared in the Windows bindings as manifest constants, 
which is normally the smart thing to do with constants. 
However, they're intended to be used as lvalues with the COM 
API, so I had to save them off in local variables in order to 
take their addresses. You can do whatever you want with your 
own declarations, of course.


You don't have to beleive me, but if I don't mark the methods 
extern(C++), then only 0 arg methods work.


In fact, Release does not work unless I mark it extern (C++).

So, while you may think it should work one way, and maybe it does 
for you in some case, it doesn't for me and has given me quite an 
amount of grief.


Regardless of what you think, I can prove that the code won't 
work when it is marked extern(Windows) and works when it is 
marked extern (C++)... so what you should be asking yourself is 
why it is doing that rather than assuming I'm making it up or 
doing something wrong.










Re: C++ interface vs D and com

2016-07-12 Thread Mike Parker via Digitalmars-d-learn

On Wednesday, 13 July 2016 at 02:49:54 UTC, Adam Sansier wrote:

On Wednesday, 13 July 2016 at 02:34:14 UTC, Mike Parker wrote:


What happens when you declare an interface that extends from 
IUnknown (and not extern(C++)), then cast the pointer returned 
from the COM API? It should just work without needing to muck 
around with the vtable.


That was what I tried first, It didn't work. I don't know what 
the problem though. I either get an access violation or the 
functions don't do anything.


Perhaps you forgot to call CoInitialize{Ex}?




I think it's more complex because without extern(C++) the 
vtable is in a different place than expected(it's offset by 1), 
so simple casting does not work.


"A COM interface differs from a regular interface in that there 
is no object.Interface entry in vtbl[0]; the entries vtbl[0..$] 
are all the virtual function pointers, in the order that they 
were declared. This matches the COM object layout used by 
Windows.


A C++ interface differs from a regular interface in that it 
matches the layout of a C++ class using single inheritance on 
the target machine. "


You don't need extern(C++) for COM interfaces. There are several 
declared in the Windows bindings that each inherit from IUnknown 
and there's no extern(C++) in sight (they existed long before C++ 
support did). Here's a working example using one of them, 
IShellLinkW, declared in core.sys.windows.shlobj.


```
import core.sys.windows.windows,
   core.sys.windows.shlobj,
   core.sys.windows.com;

pragma(lib, "Ole32");

void main()
{
IShellLinkW iface;
auto shellLinkCLSID = CLSID_ShellLink;
auto shellLinkIID = IID_IShellLinkW;

CoInitialize(null);
scope(exit)CoUninitialize();

auto hr = CoCreateInstance(
,
null,
CLSCTX_INPROC_SERVER,
,
cast(void**)
);
if(SUCCEEDED(hr)) {
import std.stdio : writeln;
writeln("Got it!");
iface.Release();
}
else throw new Exception("Failed to create IShellLink 
instance");

}
```

There's a minor annoyance here in that the IID constants are all 
declared in the Windows bindings as manifest constants, which is 
normally the smart thing to do with constants. However, they're 
intended to be used as lvalues with the COM API, so I had to save 
them off in local variables in order to take their addresses. You 
can do whatever you want with your own declarations, of course.


Re: C++ interface vs D and com

2016-07-12 Thread Adam Sansier via Digitalmars-d-learn

On Wednesday, 13 July 2016 at 02:34:14 UTC, Mike Parker wrote:

On Tuesday, 12 July 2016 at 23:55:55 UTC, Adam Sansier wrote:



Ok, Another hack:

iInterface x;
void** y = cast(void**)
*y = malloc(iInterface.sizeof);

x.__vptr = cast(immutable(void*)*)(*ptr);
x.func();

works.

x is the object of type iInterface. It has no object 
associated with it, basically create one using malloc and set 
it's vtable.


this avoids the need to create the class.


What happens when you declare an interface that extends from 
IUnknown (and not extern(C++)), then cast the pointer returned 
from the COM API? It should just work without needing to muck 
around with the vtable.


That was what I tried first, It didn't work. I don't know what 
the problem though. I either get an access violation or the 
functions don't do anything.


I think it's more complex because without extern(C++) the vtable 
is in a different place than expected(it's offset by 1), so 
simple casting does not work.


"A COM interface differs from a regular interface in that there 
is no object.Interface entry in vtbl[0]; the entries vtbl[0..$] 
are all the virtual function pointers, in the order that they 
were declared. This matches the COM object layout used by Windows.


A C++ interface differs from a regular interface in that it 
matches the layout of a C++ class using single inheritance on the 
target machine. "




Re: C++ interface vs D and com

2016-07-12 Thread Adam Sansier via Digitalmars-d-learn

On Wednesday, 13 July 2016 at 02:25:35 UTC, Jesse Phillips wrote:

On Tuesday, 12 July 2016 at 15:09:26 UTC, Adam Sansier wrote:
So, com throughs me a interface ptr and I need to map it to an 
interface. When I do, I get an access violation.


I have an (com) ptr and an interface. How do I link them up so 
I can call the functions?


I marked the interface extern(C++) so it's a C++ style 
interface.
 The first field of a COM object is a pointer to its vtable.  
This is still true in extern(C++) D, right? The calling 
convention is thiscall.


https://dlang.org/spec/cpp_interface.html


I'm not the best person to answer your questions here, but if 
you're working with COM you do not want to declare them as 
extern(C++). D supported COM long before it did direct C++ 
interfacing.


You can look at how Juno interfaces with Windows COM objects:

https://github.com/JesseKPhillips/Juno-Windows-Class-Library/blob/master/source/juno/xml/msxml.d#L226

You'll notice that it inherits from IDispatch instead of 
IUnknown, Juno defines that interface.


https://github.com/JesseKPhillips/Juno-Windows-Class-Library/blob/master/source/juno/com/core.d#L2063

Juno tries to make it easier to write and interface with COM, 
but I've only been keeping it compiling and haven't gotten to 
writing my own stuff (I've run into issues with manifest files 
an such). It would be awesome if you found it useful and could 
improve on the experience.


https://github.com/JesseKPhillips/Juno-Windows-Class-Library/wiki



I think you would have to explain to me why it would be worth 
switching. At least in my case it is already working and seems to 
be much easier than a quick casual glance at juno. I don't need a 
full blown COM lib at this point though and maybe it only works 
for my use case(Where CoCreateInstance returns the interface ptr 
directly and no need to query).


I think extern(C++) is necessary because of the calling 
convention. I could be wrong. extern(Windows) definitely doesn't 
work. Why the methods I'm using might seem a bit hackish, they 
are working and is rather simple(a few lines of code), it might 
not be robust though.


Maybe you could write up a little more on the juno 
readme.markdown file to explain it's purpose and capabilities.


It seems like it provides server capabilities, which at don't 
need at the moment(maybe later), and seems quite large. My com 
code is basically about 10 lines total + the interface.


If you can convince me to try it out, I might... but doing com 
isn't my primary goal here and I seem to have finished up what I 
was trying to achieve(my use case is probably relatively simple 
though). Last thing I want to do is get bogged down in this 
stuff, which feels clumsy and not well documented(Both the D and 
C sides)








Re: C++ interface vs D and com

2016-07-12 Thread Mike Parker via Digitalmars-d-learn

On Tuesday, 12 July 2016 at 23:55:55 UTC, Adam Sansier wrote:



Ok, Another hack:

iInterface x;
void** y = cast(void**)
*y = malloc(iInterface.sizeof);

x.__vptr = cast(immutable(void*)*)(*ptr);
x.func();

works.

x is the object of type iInterface. It has no object associated 
with it, basically create one using malloc and set it's vtable.


this avoids the need to create the class.


What happens when you declare an interface that extends from 
IUnknown (and not extern(C++)), then cast the pointer returned 
from the COM API? It should just work without needing to muck 
around with the vtable.


Re: C++ interface vs D and com

2016-07-12 Thread Jesse Phillips via Digitalmars-d-learn

On Tuesday, 12 July 2016 at 15:09:26 UTC, Adam Sansier wrote:
So, com throughs me a interface ptr and I need to map it to an 
interface. When I do, I get an access violation.


I have an (com) ptr and an interface. How do I link them up so 
I can call the functions?


I marked the interface extern(C++) so it's a C++ style 
interface.
 The first field of a COM object is a pointer to its vtable.  
This is still true in extern(C++) D, right? The calling 
convention is thiscall.


https://dlang.org/spec/cpp_interface.html


I'm not the best person to answer your questions here, but if 
you're working with COM you do not want to declare them as 
extern(C++). D supported COM long before it did direct C++ 
interfacing.


You can look at how Juno interfaces with Windows COM objects:

https://github.com/JesseKPhillips/Juno-Windows-Class-Library/blob/master/source/juno/xml/msxml.d#L226

You'll notice that it inherits from IDispatch instead of 
IUnknown, Juno defines that interface.


https://github.com/JesseKPhillips/Juno-Windows-Class-Library/blob/master/source/juno/com/core.d#L2063

Juno tries to make it easier to write and interface with COM, but 
I've only been keeping it compiling and haven't gotten to writing 
my own stuff (I've run into issues with manifest files an such). 
It would be awesome if you found it useful and could improve on 
the experience.


https://github.com/JesseKPhillips/Juno-Windows-Class-Library/wiki


Re: C++ interface vs D and com

2016-07-12 Thread Adam Sansier via Digitalmars-d-learn

On Tuesday, 12 July 2016 at 22:55:05 UTC, Adam Sansier wrote:
So, the problem now, is how to take the interface, which is 
simple, no implementation, and either create the 
implementation or create a sort of simple empty proxy that can 
be used to instantiate the interface?




I mean automatically of course. I believe D already has some 
library solution for this but haven't looked them up yet.


Ok, Another hack:

iInterface x;
void** y = cast(void**)
*y = malloc(iInterface.sizeof);

x.__vptr = cast(immutable(void*)*)(*ptr);
x.func();

works.

x is the object of type iInterface. It has no object associated 
with it, basically create one using malloc and set it's vtable.


this avoids the need to create the class.





Re: C++ interface vs D and com

2016-07-12 Thread Adam Sansier via Digitalmars-d-learn
So, the problem now, is how to take the interface, which is 
simple, no implementation, and either create the implementation 
or create a sort of simple empty proxy that can be used to 
instantiate the interface?




I mean automatically of course. I believe D already has some 
library solution for this but haven't looked them up yet.




Re: C++ interface vs D and com

2016-07-12 Thread Lodovico Giaretta via Digitalmars-d-learn

On Tuesday, 12 July 2016 at 21:21:04 UTC, Adam Sansier wrote:
On Tuesday, 12 July 2016 at 15:12:21 UTC, Lodovico Giaretta 
wrote:


I'm not an expert in this field, but did you read this[1]?

[1] https://dlang.org/spec/interface.html#com-interfaces


Yes, of course...


Well, I asked because you say you marked your interfaces as 
extern(C++), which is *not* what the spec says you should do.
Of course, because you didn't give us much infos on what's not 
working, we have to guess and point you to some generic resources.
Did you read the wiki entry[1], and had a look to some source 
code[2]? It may be useful to understand if it's a simple mistake 
on your side or some more deep issue.


[1] https://wiki.dlang.org/COM_Programming
[2] 
https://github.com/dlang/druntime/blob/master/src/core/sys/windows/com.d


Re: C++ interface vs D and com

2016-07-12 Thread Adam Sansier via Digitalmars-d-learn

On Tuesday, 12 July 2016 at 15:13:02 UTC, Adam D. Ruppe wrote:

On Tuesday, 12 July 2016 at 15:09:26 UTC, Adam Sansier wrote:
I marked the interface extern(C++) so it's a C++ style 
interface.

 The first field of a COM object is a pointer to its vtable.


If it is a COM interface, you should make it a COM interface by 
inheriting from IUnknown.


http://dlang.org/spec/interface.html#com-interfaces


Obviously... doesn't help.

There is some weirdness with the vtable.

In the C++ version it is a simple list of void*'s starting at 
offset 0. In the D version I haven't figured out what is going on 
yet. Might just be a simple mistake on my part but something 
seems aloof. I will continue to work on it, it is difficult 
without being able to really see what is going on through proper 
debugging support though and not knowing how D does things 
differently than C++ under the hood.








Re: C++ interface vs D and com

2016-07-12 Thread Adam Sansier via Digitalmars-d-learn

On Tuesday, 12 July 2016 at 15:12:21 UTC, Lodovico Giaretta wrote:

On Tuesday, 12 July 2016 at 15:09:26 UTC, Adam Sansier wrote:
So, com throughs me a interface ptr and I need to map it to an 
interface. When I do, I get an access violation.


I have an (com) ptr and an interface. How do I link them up so 
I can call the functions?


I marked the interface extern(C++) so it's a C++ style 
interface.
 The first field of a COM object is a pointer to its vtable.  
This is still true in extern(C++) D, right? The calling 
convention is thiscall.


https://dlang.org/spec/cpp_interface.html


I'm not an expert in this field, but did you read this[1]?

[1] https://dlang.org/spec/interface.html#com-interfaces


Yes, of course...


Re: C++ interface vs D and com

2016-07-12 Thread Adam D. Ruppe via Digitalmars-d-learn

On Tuesday, 12 July 2016 at 15:09:26 UTC, Adam Sansier wrote:
I marked the interface extern(C++) so it's a C++ style 
interface.

 The first field of a COM object is a pointer to its vtable.


If it is a COM interface, you should make it a COM interface by 
inheriting from IUnknown.


http://dlang.org/spec/interface.html#com-interfaces


Re: C++ interface vs D and com

2016-07-12 Thread Lodovico Giaretta via Digitalmars-d-learn

On Tuesday, 12 July 2016 at 15:09:26 UTC, Adam Sansier wrote:
So, com throughs me a interface ptr and I need to map it to an 
interface. When I do, I get an access violation.


I have an (com) ptr and an interface. How do I link them up so 
I can call the functions?


I marked the interface extern(C++) so it's a C++ style 
interface.
 The first field of a COM object is a pointer to its vtable.  
This is still true in extern(C++) D, right? The calling 
convention is thiscall.


https://dlang.org/spec/cpp_interface.html


I'm not an expert in this field, but did you read this[1]?

[1] https://dlang.org/spec/interface.html#com-interfaces


C++ interface vs D and com

2016-07-12 Thread Adam Sansier via Digitalmars-d-learn
So, com throughs me a interface ptr and I need to map it to an 
interface. When I do, I get an access violation.


I have an (com) ptr and an interface. How do I link them up so I 
can call the functions?


I marked the interface extern(C++) so it's a C++ style interface. 
 The first field of a COM object is a pointer to its vtable.  
This is still true in extern(C++) D, right? The calling 
convention is thiscall.


https://dlang.org/spec/cpp_interface.html