digitalmars.D.bugs - Problem with COM interfaces
- Dick L (32/32) Apr 11 2005 The compiler seems to doing strange things when calling a COM interface
- Chris Sauls (9/12) Apr 11 2005 Try the following -- which I admit to not having tested:
- dickl (4/21) Apr 12 2005 The problem is not related to the pointer being passed.
- Dick L (62/62) Apr 14 2005 The following bit of code shows the compiler pushing the address of the
- Thomas Kuehne (12/16) Apr 14 2005 -----BEGIN PGP SIGNED MESSAGE-----
- Dick L (6/23) Apr 14 2005 I'll do it..
- Dick L (17/17) Apr 15 2005 After a little more research it appears there are two types of COM
The compiler seems to doing strange things when calling a COM interface methods: E.g. interface foo: IUnknown { extern(Windows) int getDrivername(char *name); } ... code to initialize COM and get the pointer to the interface seems to work correctly. Now when calling getDrivername, the compiler seems to push extra stuff on the stack which caused the stack to get corrupted and memory to get corrupted as getDrivername writes to the wrong address e.g. char []name; char *p=name; //for viewing during debuging theinterface.getDrivername(p); the assembly looks like this: char *p=name; 004030B9 lea edx,[esi+8] 004030BC mov dword ptr [p],edx theinterface.getDrivername(p); 004030BF push edx // the address of the string 004030C0 mov ebx,dword ptr [this] // now the address of the interface is pushed on the stack 004030C3 add ebx,10h // the interface is expecting only 1 arg so there now are stack problems 004030C6 mov eax,dword ptr [ebx] // the interface thinks this is the ptr to write to so memory gets corrupted 004030C8 push eax 004030C9 mov edi,dword ptr [eax] // the interface method is called (correctly) 004030CB call dword ptr [edi+10h]
Apr 11 2005
Dick L wrote:char []name; char *p=name; //for viewing during debuging theinterface.getDrivername(p);Try the following -- which I admit to not having tested: Or maybe even just: -- Chris Sauls
Apr 11 2005
The problem is not related to the pointer being passed. Oddly enough, what seems to work is declaring all the methods in the interface as extern(D) rather than extern(Windows) Chris Sauls wrote:Dick L wrote:char []name; char *p=name; //for viewing during debuging theinterface.getDrivername(p);Try the following -- which I admit to not having tested: Or maybe even just: -- Chris Sauls
Apr 12 2005
The following bit of code shows the compiler pushing the address of the interface on the stack before calling the interface method. When extern(Windows) is changed to extern(D) the compiler doesn't do that. module test; interface foo { extern(Windows): int getName(char *p); int init(void *); } int main() { foo theInterface; char []Name; theInterface.getName(cast(char *)Name); return true; } int main() 00402010 enter 10h,0 { foo theInterface; 00402014 xor eax,eax 00402016 mov dword ptr [theInterface],eax char []Name; 00402019 mov dword ptr [Name],eax 0040201C mov dword ptr [ebp-4],eax theInterface.getName(cast(char *)Name); 0040201F push dword ptr [ebp-4] 00402022 push eax 00402023 mov ecx,dword ptr [eax] 00402025 call dword ptr [ecx+4] return true; =========================== module test; interface foo { extern(D): int getName(char *p); int init(void *); } int main() { foo theInterface; char []Name; theInterface.getName(cast(char *)Name); return true; } int main() 00402010 enter 10h,0 { foo theInterface; 00402014 xor eax,eax 00402016 mov dword ptr [theInterface],eax char []Name; 00402019 mov dword ptr [Name],eax 0040201C mov dword ptr [ebp-4],eax theInterface.getName(cast(char *)Name); 0040201F push dword ptr [ebp-4] 00402022 mov ecx,dword ptr [eax] 00402024 call dword ptr [ecx+4] return true;
Apr 14 2005
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Dick L schrieb am Thu, 14 Apr 2005 09:54:23 -0400:The following bit of code shows the compiler pushing the address of the interface on the stack before calling the interface method. When extern(Windows) is changed to extern(D) the compiler doesn't do that.<snip> Could someone please write a test case that checks for this via assert? (My Windows knowledge is very limited, so I done't know what to expect) Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFCXxzX3w+/yD4P9tIRAtenAJ9hfO4iSctytJJkMVUqamjoJPkslACfeR2r b7lHikSTNlhucEPhcqgTJ1A= =L4Rf -----END PGP SIGNATURE-----
Apr 14 2005
I'll do it.. I'd like to get some confirmation its a compiler bug rather than my stupidity before I do.. dick "Thomas Kuehne" <thomas-dloop kuehne.thisisspam.cn> wrote in message news:nvi3j2-8re.ln1 lnews.kuehne.cn...-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Dick L schrieb am Thu, 14 Apr 2005 09:54:23 -0400:The following bit of code shows the compiler pushing the address of the interface on the stack before calling the interface method. When extern(Windows) is changed to extern(D) the compiler doesn't do that.<snip> Could someone please write a test case that checks for this via assert? (My Windows knowledge is very limited, so I done't know what to expect) Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFCXxzX3w+/yD4P9tIRAtenAJ9hfO4iSctytJJkMVUqamjoJPkslACfeR2r b7lHikSTNlhucEPhcqgTJ1A= =L4Rf -----END PGP SIGNATURE-----
Apr 14 2005
After a little more research it appears there are two types of COM interfaces: The first requires the 'this' pointer of the interface to be past when calling methods. E.g. Direct X The second does not expect a this pointer to be pasted. E.g. interfaces written in C I wrote a simple test in CPP and it seems the default behaviour for the MSVC compiler is to not pass the 'this' pointer. The MSC header files for all the MS interfaces seem to work some magic and tell the compiler to pass the this pointer. Hard to tell what is going on with all the header files included, macros and #defined stuff in there. So.... I think simplest thing to do is update the interface documentation to say the default D implementation will pass a pointer to the interface when calling the interface methods. If you don't want the this pointer to be passed, declare the interface as "extern(D)". It would probably be better if "extern(C)" did this as its a little more obvious.
Apr 15 2005