[fpc-pascal] DirectX applications crash

Felipe Monteiro de Carvalho felipemonteiro.carvalho at gmail.com
Tue Mar 17 00:59:34 CET 2009


Hello,

I've always had a problem with using COM with Free Pascal. If I
release the interfaces, then the application crashes without reason
somewhere unrelated with the code to do the actual release. In the
following example I used the DirectX units from clootie:

http://www.clootie.ru/fpc/index.html

When I use _release I get this crash:

(gdb) run
Starting program: C:\Documents and Settings\Felipe\Meus documentos\felipedocs\Ar
tigos\Lazarusbuch\kapitel_5/directxcube.exe

Program received signal SIGSEGV, Segmentation fault.
0x00407c96 in fpc_intf_decr_ref ()
(gdb) bt
#0  0x00407c96 in fpc_intf_decr_ref ()
#1  0x0040194d in P$DIRECTXCUBE_finalize_implicit () at directxcube.pas:134
#2  0x004097a4 in SYSTEM_FINALIZEUNITS ()
#3  0x00000000 in ?? ()
(gdb)

If I don't release the interfaces then no exception occurs. I always
have this problem when using DirectX with Free Pascal. Clootie has no
forum, so I thought that asking here would be the best idea ...

Here is the test app which I converted from a C tutorial for directx:

program directxcube;

{$mode delphi}

uses
  Classes, SysUtils,
  // include the basic windows header files and the Direct3D header file
  Windows,
  Direct3D9, D3DX9;

var
  // global declarations
  d3d: IDirect3D9;    // the pointer to our Direct3D interface
  d3ddev: IDirect3DDevice9;    // the pointer to the device class

// function prototypes
procedure initD3D(hWnd: HWND); forward;    // sets up and initializes Direct3D
procedure render_frame(); forward;    // renders a single frame
procedure cleanD3D(); forward;   // closes Direct3D and releases memory

// the WindowProc function prototype
//function WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

// this is the main message handler for the program
function WindowProc(_hWnd: HWND; _message: UINT; _wParam: WPARAM;
_lParam: LPARAM): LRESULT; stdcall;
begin
  if _message = WM_DESTROY then
  begin
    PostQuitMessage(0);
    Result := 0;
    Exit;
  end;

  Result := DefWindowProc (_hWnd, _message, _wParam, _lParam);
end;

// this function initializes and prepares Direct3D for use
procedure initD3D(hWnd: HWND);
var
  d3dpp: D3DPRESENT_PARAMETERS;    // create a struct to hold various
device information
begin
  d3d := Direct3DCreate9(D3D_SDK_VERSION);    // create the Direct3D interface

  FillChar(d3dpp, sizeof(d3dpp), 0);    // clear out the struct for use
  d3dpp.Windowed := TRUE;    // program windowed, not fullscreen
  d3dpp.SwapEffect := D3DSWAPEFFECT_DISCARD;    // discard old frames
  d3dpp.hDeviceWindow := hWnd;    // set the window to be used by Direct3D

  // create a device class using this information and information from
the d3dpp stuct
  d3d.CreateDevice(D3DADAPTER_DEFAULT,
                      D3DDEVTYPE_HAL,
                      hWnd,
                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                      @d3dpp,
                      d3ddev);
end;

// this is the function used to render a single frame
procedure render_frame();
begin
    // clear the window to a deep blue
    d3ddev.Clear(0, nil, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0, 0);

    d3ddev.BeginScene();    // begins the 3D scene

    // do 3D rendering on the back buffer here

    d3ddev.EndScene();    // ends the 3D scene

    d3ddev.Present(nil, nil, 0, nil);   // displays the created frame
on the screen
end;

// this is the function that cleans up Direct3D and COM
procedure cleanD3D();
begin
  d3ddev._Release();    // close and release the 3D device
  d3d._Release();    // close and release Direct3D
end;

var
  _hWnd: HWND;
  wc: WNDCLASSEX;
  _msg: MSG;
  starting_point: Cardinal;
begin
  FillChar(wc, sizeof(WNDCLASSEX), 0);

  wc.cbSize := sizeof(WNDCLASSEX);
  wc.style := CS_HREDRAW or CS_VREDRAW;
  wc.lpfnWndProc := WindowProc;
  wc.hInstance := hInstance;
  wc.hCursor := LoadCursor(0, IDC_ARROW);
  wc.hbrBackground := HBRUSH(COLOR_WINDOW);
  wc.lpszClassName := 'WindowClass';

  RegisterClassEx(@wc);

  _hWnd := CreateWindowEx(0,
                         'WindowClass',
                         'Our First Direct3D Program',
                         WS_OVERLAPPEDWINDOW,
                         300, 300,
                         640, 480,
                         0,
                         0,
                         hInstance,
                         nil);

  ShowWindow(_hWnd, SW_SHOW);

  // set up and initialize Direct3D
  initD3D(_hWnd);

  // enter the main loop:
  while (True) do
  begin
    starting_point := GetTickCount();

    if (PeekMessage(_msg, 0, 0, 0, PM_REMOVE)) then
    begin
      if (_msg.message = WM_QUIT) then Break;

      TranslateMessage(_msg);
      DispatchMessage(_msg);
    end;

    render_frame();

    while ((GetTickCount() - starting_point) < 25) do;
  end;

  // clean up DirectX and COM
  cleanD3D(); // Comment or uncomment
end.



More information about the fpc-pascal mailing list