Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi D3D9 Hook bzw. als "proxy.dll" (https://www.delphipraxis.net/142249-d3d9-hook-bzw-als-proxy-dll.html)

Apollonius 27. Okt 2009 17:58

Re: D3D9 Hook bzw. als "proxy.dll"
 
Was heißt denn jetzt "funktioniert nicht"? Hast du das mal debuggt?
Christian, der Funktionsprototyp darf nicht verändert werden. Wenn man als Result ein Interface, dynamisches Array, String oder Variant verwendet, wird intern ein out-Parameter verwendet - man verändert also die Aufrufkonvention.

Dezipaitor 27. Okt 2009 18:10

Re: D3D9 Hook bzw. als "proxy.dll"
 
Um was geht es? COM Methoden oder Standardfunktionen?
Der Result ist hier ein Pointer, original ist ein Interface.

Apollonius 27. Okt 2009 18:23

Re: D3D9 Hook bzw. als "proxy.dll"
 
Naja, die C++-Deklaration sieht so aus:
Code:
IDirect3D9 * Direct3DCreate9(
  UINT SDKVersion
);
Und wenn ich in Delphi schreibe
Delphi-Quellcode:
function Direct3DCreate9(SDKVersion: Cardinal): IDirect3D9; stdcall;
dürfte das in C++ so heraus kommen:
Code:
void Direct3DCreate9(UINT SDKVersion, IDirect3D9** result);
Sofern ich mich nicht irre, werden Typen mit RefCount (d.h. finalisierungsbedürftige Typen) immer als out-Parameter zurückgegeben.
Nebenbei bemerkt scheint beim Threadersteller ein stdcall verloren gegangen zu sein.

Dezipaitor 27. Okt 2009 18:44

Re: D3D9 Hook bzw. als "proxy.dll"
 
Ich bezog mich garnicht auf die Übersetzung, sondern nur, dass man Interfaces als Result zurückgeben kann.

Aber stimmt schon, wenn man es übersetzt dann über einen Pointer. D.h. die Routine muss gekapselt werden und die neue Routine darf nur öffentlich sein.

Allerdings, der Header definiert das stdcall garnicht.

Apollonius 27. Okt 2009 18:53

Re: D3D9 Hook bzw. als "proxy.dll"
 
Stimmt, das stdcall fehlt - sehr seltsam. Register ist es allerdings auf keinen Fall.

Remko 27. Okt 2009 20:17

Re: D3D9 Hook bzw. als "proxy.dll"
 
I think this is a Delphi bug, I remember it because I had a problem with some other winapi call that returned an interface.
I quickly tested this (I used IUnknown because I don't have DirectX):

Delphi-Quellcode:
function Direct3DCreate9(SDKVersion: Cardinal): IUnknown; stdcall; external 'd3d9.dll';

procedure TForm2.Button1Click(Sender: TObject);
var
  Unknown: IUnknown;
begin
  Unknown := Direct3DCreate9(32);
end;
When I look in the CPU window we can see the problem:
Delphi-Quellcode:
Unit2.pas.31: Unknown := Direct3DCreate9(32);
004A3B0F 6A20             push $20
004A3B11 8D45F8           lea eax,[ebp-$08]
004A3B14 50               push eax
004A3B15 E8CEFFFFFF      call Direct3DCreate9
For some reason Delphi put's the result (which is in eax when using stdcall) on stack (push eax).

If I declare like this it looks ok:
Delphi-Quellcode:
function Direct3DCreate9(SDKVersion: Cardinal): Pointer; stdcall; external 'd3d9.dll';

procedure TForm2.Button1Click(Sender: TObject);
var
  Unknown: IUnknown;
begin
  Pointer(Unknown) := Direct3DCreate9(32);
end;
The CPU window shows:
Delphi-Quellcode:
Unit2.pas.31: Pointer(Unknown) := Direct3DCreate9(32);
004A3B0F 6A20             push $20
004A3B11 E8D2FFFFFF      call Direct3DCreate9
004A3B16 8945F8           mov [ebp-$08],eax

Apollonius 27. Okt 2009 20:40

Re: D3D9 Hook bzw. als "proxy.dll"
 
Delphi doesn't really put the result on stack - it uses an out Parameter. You see that the calling routine pushes the address ebp - 8 which is the address of the Unknown variable.
I think that the modified signature using an out-parameter instead of the usual result is reasonable from a design standpoint. Returning an interface in eax is always bad - and never happens in the usual COM context - because it poses a severe problem with respect to exception handling. If an exception occurs when the called routine returns, the interface cannot be released correctly because it is lost when the exception is thrown. Using the Delphi design, on the other hand, the caller retains a reference to the interface and will release it due to the auto-generated try-finally.
To sum it up, the Delphi semantics is different to the C++ semantics and perhaps different from naive expectations, but it is the best way to do it in my opinion. The error is on the side of the Direct3D developers because they designed their function to break COM rules.

Remko 27. Okt 2009 20:47

Re: D3D9 Hook bzw. als "proxy.dll"
 
Well, the way I see it it's not a design discussion (although I agree that the Delphi (Safecall) solution is elegant) but what's happening here is that Delphi put's 2 pointers on stack while the dll expects only one. Another example where this happens is SHOpenRegStream2.

Apollonius 27. Okt 2009 21:10

Re: D3D9 Hook bzw. als "proxy.dll"
 
Sure, as I said, you cannot naively translate from/to C++. But SHOpenRegStream2 poses the very same exception problem I described above - I regard this as a bug. By forcing you to think about untyped pointers and reference counting, Delphi doesn't hide this bug. Delphi's interfaces are made to be fail-safe with the automatic reference counting - but this safety simply cannot be provided in the case of SHOpenRegStream2 et al., and Delphi doesn't give any illusions about this.

Dezipaitor 27. Okt 2009 21:19

Re: D3D9 Hook bzw. als "proxy.dll"
 
hat niemand die Deklaration
Delphi-Quellcode:
function(SDKVersion: LongWord): ^IDirect3D9; stdcall
mal ausprobiert?

[UPDATE]
Ich meinte mit ^


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:11 Uhr.
Seite 2 von 3     12 3      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz