Jump to page: 1 2 3
Thread overview
C++ interface vs D and com
Jul 12, 2016
Adam Sansier
Jul 12, 2016
Lodovico Giaretta
Jul 12, 2016
Adam Sansier
Jul 12, 2016
Lodovico Giaretta
Jul 12, 2016
Adam Sansier
Jul 12, 2016
Adam Sansier
Jul 12, 2016
Adam Sansier
Jul 13, 2016
Mike Parker
Jul 13, 2016
Adam Sansier
Jul 13, 2016
Mike Parker
Jul 13, 2016
Adam Sansier
Jul 13, 2016
Mike Parker
Jul 13, 2016
Adam Sansier
Jul 13, 2016
John
Jul 13, 2016
Adam Sansier
Jul 13, 2016
Kagamin
Jul 13, 2016
Adam Sansier
Jul 13, 2016
John
Jul 13, 2016
Adam Sansier
Jul 14, 2016
Mike Parker
Jul 14, 2016
Kagamin
Jul 13, 2016
Kagamin
Jul 12, 2016
Adam D. Ruppe
Jul 12, 2016
Adam Sansier
Jul 13, 2016
Jesse Phillips
Jul 13, 2016
Adam Sansier
Jul 13, 2016
Jesse Phillips
Jul 13, 2016
Adam Sansier
July 12, 2016
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



July 12, 2016
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
July 12, 2016
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
July 12, 2016
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...
July 12, 2016
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.





July 12, 2016
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
July 12, 2016
On Tuesday, 12 July 2016 at 22:01:41 UTC, Lodovico Giaretta wrote:
> 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

I've spent the last 2 days working on it looking up as much as I can. It's not as if there is any sensible information on it. Trust me... If you haven't done much with it, there is no way you can imagine how convoluted it is... you can pretend, but that doesn't do it justice.

Ok, I got it to work but had to completely hack it. This is not the way to go about it though! There must be a better way!

1. Change the interface in to a class, create dummy functions for all members. This is because we must be able to instantiate the interface so we can modify it's vtable ptr. With just the interface, we'll never be able to create the object(maybe malloc will do?) Abstract class won't work either for similar reasons.

The layout must look exactly like the interface(in order and include IUnknown methods).

2. change __vtbl ptr:

auto interfaceClass = new InterfaceClass();
interfaceClass.__vptr = cast(immutable(void*)*)(*ptr);

where ptr is what is returned from CoCreateInstance(if it is a direct object).

Essentially we are creating a template with InterfaceClass then swapping it's vtable with the correct one. We technically don't need to recreate the class exactly but it's required for intellisense and compiler semantics. We could use opDispatch, etc.

The vtable modification isn't bad, though. That's just a one liner.



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?

Basically the problem now is, that using this method one has to create a class and add stubs for all the methods along with all the inherited methods. This is tedious and they serve no purpose.



July 12, 2016
> 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.

July 12, 2016
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**)&x;
		*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.



July 13, 2016
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
« First   ‹ Prev
1 2 3