4

如何配置 mingw32 以交叉编译适用于 Windows 的 Direct3D 应用程序?有没有可能?我实际上已经成功编译了本教程中的代码:http ://www.directxtutorial.com/Tutorial9/B-Direct3DBasics/dx9B4.aspx - 在 Kubuntu 上使用 Code::Blocks 和 i586-mingw32msvc-g++。我需要添加#define UNICODE和删除#pragma ...部件来执行此操作,并且我使用了 /usr/i586-mingw32msvc/include 中的头文件和 mingw 包中的库。

但是我无法编译本教程中的代码:http ://www.directxtutorial.com/Tutorial9/B-Direct3DBasics/dx9B5.aspx

Mingw 没有d3dx9.h文件。所以我已经安装wine1.2-dev了带有与 Windows 相关的头文件的 wine 版本的软件包,但现在我遇到了错误:

#define UNICODE

-------------- Build: Debug in d3d ---------------

i586-mingw32msvc-g++ -Wall  -g    -I/usr/include/wine/windows  -c /home/silmeth/programowanie/codeblocks/d3d/main.cpp -o obj/Debug/main.o
/home/silmeth/programowanie/codeblocks/d3d/main.cpp: In function ‘int WinMain(HINSTANCE__*, HINSTANCE__*, CHAR*, int)’:
/home/silmeth/programowanie/codeblocks/d3d/main.cpp:50: error: invalid conversion from ‘const wchar_t*’ to ‘const WCHAR*’
/home/silmeth/programowanie/codeblocks/d3d/main.cpp:56: error: invalid conversion from ‘const wchar_t*’ to ‘const WCHAR*’
/home/silmeth/programowanie/codeblocks/d3d/main.cpp:56: error:   initializing argument 2 of ‘HWND__* CreateWindowExW(DWORD, const WCHAR*, const WCHAR*, DWORD, INT, INT, INT, INT, HWND__*, HMENU__*, HINSTANCE__*, void*)’
/home/silmeth/programowanie/codeblocks/d3d/main.cpp:56: error: invalid conversion from ‘const wchar_t*’ to ‘const WCHAR*’
/home/silmeth/programowanie/codeblocks/d3d/main.cpp:56: error:   initializing argument 3 of ‘HWND__* CreateWindowExW(DWORD, const WCHAR*, const WCHAR*, DWORD, INT, INT, INT, INT, HWND__*, HMENU__*, HINSTANCE__*, void*)’
/home/silmeth/programowanie/codeblocks/d3d/main.cpp: In function ‘void render_frame()’:
/home/silmeth/programowanie/codeblocks/d3d/main.cpp:158: warning: taking address of temporary
/home/silmeth/programowanie/codeblocks/d3d/main.cpp:159: warning: taking address of temporary
/home/silmeth/programowanie/codeblocks/d3d/main.cpp:160: warning: taking address of temporary
Process terminated with status 1 (0 minutes, 0 seconds)
5 errors, 3 warnings

并且没有#define


-------------- Build: Debug in d3d ---------------

i586-mingw32msvc-g++ -Wall  -g    -I/usr/include/wine/windows  -c /home/silmeth/programowanie/codeblocks/d3d/main.cpp -o obj/Debug/main.o
/home/silmeth/programowanie/codeblocks/d3d/main.cpp: In function ‘int WinMain(HINSTANCE__*, HINSTANCE__*, CHAR*, int)’:
/home/silmeth/programowanie/codeblocks/d3d/main.cpp:50: error: cannot convert ‘const wchar_t [12]’ to ‘const CHAR*’ in assignment
/home/silmeth/programowanie/codeblocks/d3d/main.cpp:56: error: cannot convert ‘const wchar_t*’ to ‘const CHAR*’ for argument ‘2’ to ‘HWND__* CreateWindowExA(DWORD, const CHAR*, const CHAR*, DWORD, INT, INT, INT, INT, HWND__*, HMENU__*, HINSTANCE__*, void*)’
/home/silmeth/programowanie/codeblocks/d3d/main.cpp: In function ‘void render_frame()’:
/home/silmeth/programowanie/codeblocks/d3d/main.cpp:158: warning: taking address of temporary
/home/silmeth/programowanie/codeblocks/d3d/main.cpp:159: warning: taking address of temporary
/home/silmeth/programowanie/codeblocks/d3d/main.cpp:160: warning: taking address of temporary
Process terminated with status 1 (0 minutes, 0 seconds)
2 errors, 3 warnings

这是我要编译的整个代码:

// include the basic windows header files and the Direct3D header file
#define UNICODE //tried to comment and uncomment this
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
#include <d3dx9.h>

// define the screen resolution
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600

// include the Direct3D Library files
//#pragma comment (lib, "d3d9.lib")
//#pragma comment (lib, "d3dx9.lib")

// global declarations
LPDIRECT3D9 d3d;    // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev;    // the pointer to the device class
LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL;    // the pointer to the vertex buffer

// function prototypes
void initD3D(HWND hWnd);    // sets up and initializes Direct3D
void render_frame(void);    // renders a single frame
void cleanD3D(void);    // closes Direct3D and releases memory
void init_graphics(void);    // 3D declarations

struct CUSTOMVERTEX {FLOAT X, Y, Z; DWORD COLOR;};
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)

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


// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
    HWND hWnd;
    WNDCLASSEX wc;

    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszClassName = L"WindowClass";

    RegisterClassEx(&wc);

    hWnd = CreateWindowEx(NULL, L"WindowClass", L"Our Direct3D Program",
                          WS_OVERLAPPEDWINDOW, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,
                          NULL, NULL, hInstance, NULL);

    ShowWindow(hWnd, nCmdShow);

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

    // enter the main loop:

    MSG msg;

    while(TRUE)
    {
        while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        if(msg.message == WM_QUIT)
            break;

        render_frame();
    }

    // clean up DirectX and COM
    cleanD3D();

    return msg.wParam;
}


// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
        case WM_DESTROY:
            {
                PostQuitMessage(0);
                return 0;
            } break;
    }

    return DefWindowProc (hWnd, message, wParam, lParam);
}


// this function initializes and prepares Direct3D for use
void initD3D(HWND hWnd)
{
    d3d = Direct3DCreate9(D3D_SDK_VERSION);

    D3DPRESENT_PARAMETERS d3dpp;

    ZeroMemory(&d3dpp, sizeof(d3dpp));
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = hWnd;
    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
    d3dpp.BackBufferWidth = SCREEN_WIDTH;
    d3dpp.BackBufferHeight = SCREEN_HEIGHT;

    // create a device class using this information and the info from the d3dpp stuct
    d3d->CreateDevice(D3DADAPTER_DEFAULT,
                      D3DDEVTYPE_HAL,
                      hWnd,
                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                      &d3dpp,
                      &d3ddev);

    init_graphics();    // call the function to initialize the triangle

    d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE);    // turn off the 3D lighting
}


// this is the function used to render a single frame
void render_frame(void)
{
    d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

    d3ddev->BeginScene();

    // select which vertex format we are using
    d3ddev->SetFVF(CUSTOMFVF);

    // SET UP THE PIPELINE

    D3DXMATRIX matRotateY;    // a matrix to store the rotation information

    static float index = 0.0f; index+=0.05f;    // an ever-increasing float value

    // build a matrix to rotate the model based on the increasing float value
    D3DXMatrixRotationY(&matRotateY, index);

    // tell Direct3D about our matrix
    d3ddev->SetTransform(D3DTS_WORLD, &matRotateY);

    D3DXMATRIX matView;    // the view transform matrix

    D3DXMatrixLookAtLH(&matView,
                       &D3DXVECTOR3 (0.0f, 0.0f, 10.0f),    // the camera position
                       &D3DXVECTOR3 (0.0f, 0.0f, 0.0f),    // the look-at position
                       &D3DXVECTOR3 (0.0f, 1.0f, 0.0f));    // the up direction

    d3ddev->SetTransform(D3DTS_VIEW, &matView);    // set the view transform to matView

    D3DXMATRIX matProjection;     // the projection transform matrix

    D3DXMatrixPerspectiveFovLH(&matProjection,
                               D3DXToRadian(45),    // the horizontal field of view
                               (FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT, // aspect ratio
                               1.0f,    // the near view-plane
                               100.0f);    // the far view-plane

    d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection);    // set the projection

    // select the vertex buffer to display
    d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));

    // copy the vertex buffer to the back buffer
    d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);

    d3ddev->EndScene();

    d3ddev->Present(NULL, NULL, NULL, NULL);
}


// this is the function that cleans up Direct3D and COM
void cleanD3D(void)
{
    v_buffer->Release();    // close and release the vertex buffer
    d3ddev->Release();    // close and release the 3D device
    d3d->Release();    // close and release Direct3D
}


// this is the function that puts the 3D models into video RAM
void init_graphics(void)
{
    // create the vertices using the CUSTOMVERTEX struct
    CUSTOMVERTEX vertices[] =
    {
        { 3.0f, -3.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 255), },
        { 0.0f, 3.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
        { -3.0f, -3.0f, 0.0f, D3DCOLOR_XRGB(255, 0, 0), },
    };

    // create a vertex buffer interface called v_buffer
    d3ddev->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX),
                               0,
                               CUSTOMFVF,
                               D3DPOOL_MANAGED,
                               &v_buffer,
                               NULL);

    VOID* pVoid;    // a void pointer

    // lock v_buffer and load the vertices into it
    v_buffer->Lock(0, 0, (void**)&pVoid, 0);
    memcpy(pVoid, vertices, sizeof(vertices));
    v_buffer->Unlock();
}

我必须通过 wine MS DirectX SDK 安装吗?用代码改变一些东西?我是 DirectX 和 Windows 相关的菜鸟,但我只想交叉编译一些简单的 D3D 示例并检查它是否有效。

4

3 回答 3

5

行!我终于成功了!

不幸的是,我需要下载 Microsoft DirectX SDK(2007 年 4 月)(我无法使用 wine 安装较新的 SDK)。

然后我必须使用 wine 安装 MinGW 并安装 mingw-utils 0.3(我必须获得 reimp.exe 文件)。

然后我在 wine 的寄存器中设置 PATH 到C:\windows;C:\windows\system;C:\MinGW\bin

然后我做了wine reimp.exe "C:\Program Files\Microsoft DirectX SDK (April 2007)/Lib/x86/d3dx9.lib"。该命令生成d3dx9_33.a文件,我已将其更改d3dx9.a/usr/i586-mingw32msvc/lib/.

我还将所有缺少的头文件从 DirectX SDK 复制到/usr/i586-mingw32msvc/include.

然后......我编译了程序,将它链接到 libd3d9.a 和 libd3dx9.a,它编译、链接,它工作了!

所以好消息是:可以使用 Linux 版本的 MinGW 在 Linux 下编译 Windows DirectX 程序。

坏消息:需要使用 wine 安装一些 MinGW 实用程序和整个 MS DX SDK。

编辑

还有一件事:我需要手动制作所有与 WCHAR* 相关的铸件——如果没有完成,mingw 会报错。Goz 在这里很有帮助。

于 2010-09-28T23:29:57.520 回答
2

如果您将字符串更改为

(const WCHAR*)L"blah blah"

然后它应该编译它并不理想,但似乎 wchar_t 和 WCHAR 在 mingw 下不兼容。我不完全确定为什么它不能编译,因为 windows.h 将 WCHAR 定义为 wchar_t 的 typedef ...

于 2010-09-28T18:30:40.393 回答
1

You can also you the plain mingw crosscompiler in for instance Debian or Ubuntu, and the code for DirectX only using LoadLibrary() and GetProcAddress(). (But the tutorials on DirectX can't be used as-is then.)

于 2011-01-02T15:32:30.807 回答