繁体   English   中英

头文件链接器错误

[英]Header file linker error

我不明白为什么会出现以下错误

fatal error LNK1169: one or more multiply defined symbols found

IDirect3DDevice10Hook.h:

#include "../graphics/includes.h"
#include "../hook/FW1FontWrapper.h"
#include "../hook/BeaEngine.h"

typedef HRESULT(__stdcall *D3D11PresentHook) (IDXGISwapChain* pSwapChain,    UINT SyncInterval, UINT Flags);
typedef void(__stdcall *D3D11DrawIndexedHook) (ID3D11DeviceContext* pContext, UINT IndexCount, UINT StartIndexLocation, INT BaseVertexLocation);
typedef void(__stdcall *D3D11ClearRenderTargetViewHook) (ID3D11DeviceContext* pContext, ID3D11RenderTargetView *pRenderTargetView, const FLOAT ColorRGBA[4]);

struct HookContext {
BYTE original_code[64];
SIZE_T dst_ptr;
BYTE far_jmp[6];
};

HookContext *presenthook64;
ID3D11Device *pDevice = NULL;
ID3D11DeviceContext *pContext = NULL;

DWORD_PTR* pSwapChainVtable = NULL;
DWORD_PTR* pDeviceContextVTable = NULL;

D3D11PresentHook phookD3D11Present = NULL;
D3D11DrawIndexedHook phookD3D11DrawIndexed = NULL;
D3D11ClearRenderTargetViewHook phookD3D11ClearRenderTargetView = NULL;

IFW1Factory *pFW1Factory = NULL;
IFW1FontWrapper *pFontWrapper = NULL;

bool firstTime = true;
void* detourBuffer[3];

HRESULT  hookD3D11Present(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags);
void hookD3D11DrawIndexed(ID3D11DeviceContext *pContext, UINT IndexCount, UINT StartIndexLocation, INT BaseVertexLocation);
void  hookD3D11ClearRenderTargetView(ID3D11DeviceContext *pContext, ID3D11RenderTargetView *pRenderTargetView, const FLOAT ColorRGBA[4]);
const void* DetourFuncVTable(SIZE_T *src, const BYTE *dest, const DWORD index);
const unsigned int DisasmLengthCheck(const SIZE_T address, const unsigned int jumplength);
const void* DetourFunc64(BYTE* const src, const BYTE* dest, const unsigned int jumplength);
DWORD InitializeHook(LPVOID);

这是我的头文件,我具有IDirect3DDevice10Hook.cpp并且没有收到代码错误,我在头文件中创建了该函数,因为我想在我的解决方案的另一个文件中使用它们。

但是,当我在dllmain.cpp中使用代码时,一切都很好,并且它的工作正常,并且没有错误,这是我的dllmain.cpp:

#include "../clientscript/core/graphics/includes.h"
#include "core\hook\FW1FontWrapper.h"
#include "core\hook\BeaEngine.h"

typedef HRESULT(__stdcall *D3D11PresentHook) (IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags);
typedef void(__stdcall *D3D11DrawIndexedHook) (ID3D11DeviceContext* pContext, UINT IndexCount, UINT StartIndexLocation, INT BaseVertexLocation);
typedef void(__stdcall *D3D11ClearRenderTargetViewHook) (ID3D11DeviceContext* pContext, ID3D11RenderTargetView *pRenderTargetView, const FLOAT ColorRGBA[4]);

struct HookContext {
BYTE original_code[64];
SIZE_T dst_ptr;
BYTE far_jmp[6];
};

HookContext *presenthook64;
ID3D11Device *pDevice = NULL;
ID3D11DeviceContext *pContext = NULL;

DWORD_PTR* pSwapChainVtable = NULL;
DWORD_PTR* pDeviceContextVTable = NULL;

D3D11PresentHook phookD3D11Present = NULL;
D3D11DrawIndexedHook phookD3D11DrawIndexed = NULL;
D3D11ClearRenderTargetViewHook phookD3D11ClearRenderTargetView = NULL;

IFW1Factory *pFW1Factory = NULL;
IFW1FontWrapper *pFontWrapper = NULL;

bool firstTime = true;
void* detourBuffer[3];

// hookD3D11Present*
HRESULT __stdcall hookD3D11Present(IDXGISwapChain* pSwapChain, UINT     SyncInterval, UINT Flags)
{
    if (firstTime)
    {
        pSwapChain->GetDevice(__uuidof(pDevice), (void**)&pDevice);
        pDevice->GetImmediateContext(&pContext);
        FW1CreateFactory(FW1_VERSION, &pFW1Factory);
        pFW1Factory->CreateFontWrapper(pDevice, L"Impact", &pFontWrapper);
        pFW1Factory->Release();
        firstTime = false;
     }
     pFontWrapper->DrawString(pContext, L"Test Test", 10.0f, 16.0f, 16.0f, 0xffff1612, FW1_RESTORESTATE);
     return phookD3D11Present(pSwapChain, SyncInterval, Flags);
}

// hookD3D11DrawIndexed*
void __stdcall hookD3D11DrawIndexed(ID3D11DeviceContext* pContext, UINT IndexCount, UINT StartIndexLocation, INT BaseVertexLocation)
{
    return phookD3D11DrawIndexed(pContext, IndexCount, StartIndexLocation, BaseVertexLocation);
}

// hookD3D11ClearRenderTargetView*
void __stdcall hookD3D11ClearRenderTargetView(ID3D11DeviceContext* pContext,      ID3D11RenderTargetView *pRenderTargetView, const FLOAT ColorRGBA[4])
{
return phookD3D11ClearRenderTargetView(pContext, pRenderTargetView, ColorRGBA);
}

// DetourFuncVTable*
const void* DetourFuncVTable(SIZE_T* src, const BYTE* dest, const DWORD index)
{
    DWORD dwVirtualProtectBackup;
    SIZE_T* const indexPtr = &src[index];
    const void* origFunc = (void*)*indexPtr;
    VirtualProtect(indexPtr, sizeof(SIZE_T), PAGE_EXECUTE_READWRITE, &dwVirtualProtectBackup);
    *indexPtr = (SIZE_T)dest;
    VirtualProtect(indexPtr, sizeof(SIZE_T), dwVirtualProtectBackup, &dwVirtualProtectBackup);
    return origFunc;
 }

// DisasmLengthCheck*
const unsigned int DisasmLengthCheck(const SIZE_T address, const unsigned int jumplength)
{
    DISASM disasm;
    memset(&disasm, 0, sizeof(DISASM));
    disasm.EIP = (UIntPtr)address;
    disasm.Archi = 0x40;
    unsigned int processed = 0;
    while (processed < jumplength)
    {
        const int len = Disasm(&disasm);
        if (len == UNKNOWN_OPCODE) ++disasm.EIP;
        else
        {
            processed += len;
            disasm.EIP += len;
        }
    }
    return processed;
}

// DetourFunc64*
const void* DetourFunc64(BYTE* const src, const BYTE* dest, const unsigned int jumplength)
{
    // Allocate a memory page that is going to contain executable code.
    MEMORY_BASIC_INFORMATION mbi;
    for (SIZE_T addr = (SIZE_T)src; addr > (SIZE_T)src - 0x80000000; addr = (SIZE_T)mbi.BaseAddress - 1)
    {
        if (!VirtualQuery((LPCVOID)addr, &mbi, sizeof(mbi))) break;
        if (mbi.State == MEM_FREE) if (presenthook64 =    (HookContext*)VirtualAlloc(mbi.BaseAddress, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE)) break;
    }
    // If allocating a memory page failed, the function failed.
    if (!presenthook64)
    {
        return NULL;
    }
    // Select a pointer slot for the memory page to be freed on unload.
    for (int i = 0; i < sizeof(detourBuffer) / sizeof(void*); ++i)
    {
        if (!detourBuffer[i])
        {
            detourBuffer[i] = presenthook64;
            break;
        }
    }
    // Save original code and apply detour. The detour code is:
    BYTE detour[] = { 0x50, 0x48, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x87, 0x04, 0x24, 0xC3 };
    const unsigned int length = DisasmLengthCheck((SIZE_T)src, jumplength);
    memcpy(presenthook64->original_code, src, length);
    memcpy(&presenthook64->original_code[length], detour, sizeof(detour));
    *(SIZE_T*)&presenthook64->original_code[length + 3] = (SIZE_T)src + length;
    // Build a far jump to the destination function.
    *(WORD*)&presenthook64->far_jmp = 0x25FF;
    *(DWORD*)(presenthook64->far_jmp + 2) = (DWORD)((SIZE_T)presenthook64 - (SIZE_T)src + FIELD_OFFSET(HookContext, dst_ptr) - 6);
    presenthook64->dst_ptr = (SIZE_T)dest;
    // Write the hook to the original function.
    DWORD flOld = 0;
    VirtualProtect(src, 6, PAGE_EXECUTE_READWRITE, &flOld);
    memcpy(src, presenthook64->far_jmp, sizeof(presenthook64->far_jmp));
    VirtualProtect(src, 6, flOld, &flOld);
    // Return a pointer to the original code.
    return presenthook64->original_code;
}

// InitializeHook*
DWORD __stdcall InitializeHook(LPVOID)
{
    HWND hWnd = GetForegroundWindow();
    IDXGISwapChain* pSwapChain;
    D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
    DXGI_SWAP_CHAIN_DESC swapChainDesc;

    ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
    swapChainDesc.BufferCount = 1;
    swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapChainDesc.OutputWindow = hWnd;
    swapChainDesc.SampleDesc.Count = 1;
    swapChainDesc.Windowed = TRUE;//((GetWindowLong(hWnd, GWL_STYLE) & WS_POPUP) != 0) ? FALSE : TRUE;
    swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;

    D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, &featureLevel, 1, D3D11_SDK_VERSION, &swapChainDesc, &pSwapChain, &pDevice, NULL, &pContext);
    pSwapChainVtable = (DWORD_PTR*)pSwapChain;
    pSwapChainVtable = (DWORD_PTR*)pSwapChainVtable[0];
    pDeviceContextVTable = (DWORD_PTR*)pContext;
    pDeviceContextVTable = (DWORD_PTR*)pDeviceContextVTable[0];

    phookD3D11Present =  (D3D11PresentHook)DetourFunc64((BYTE*)pSwapChainVtable[8], (BYTE*)hookD3D11Present, 16);
    phookD3D11DrawIndexed = (D3D11DrawIndexedHook)DetourFunc64((BYTE*)pDeviceContextVTable[12], (BYTE*)hookD3D11DrawIndexed, 16);
    phookD3D11ClearRenderTargetView = (D3D11ClearRenderTargetViewHook)DetourFunc64((BYTE*)pDeviceContextVTable[50], (BYTE*)hookD3D11ClearRenderTargetView, 16);

    pDevice->Release();
    pContext->Release();
    pSwapChain->Release();
    return NULL;
}

BOOL __stdcall DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved)
{
    switch (dwReason)
    {
        case DLL_PROCESS_ATTACH:
        {
            memset(detourBuffer, 0, sizeof(detourBuffer) * sizeof(void*));
            CreateThread(NULL, 0, InitializeHook, NULL, 0, NULL);
        }
        case DLL_PROCESS_DETACH:
        {
            if (pFontWrapper) pFontWrapper->Release();
            for (int i = 0; i < sizeof(detourBuffer) / sizeof(void*); ++i) if (detourBuffer[i]) VirtualFree(detourBuffer[i], 0, MEM_RELEASE);
        }
    }
    return TRUE;
}

我该如何解决? 我的目标是创建头文件并使用dllmain.cpp中的函数,但出现此错误,谢谢帮手:)

也许您可以添加一些标题保护:

#ifndef _IDIRECT3DDEVICE10HOOK_H_
#define _IDIRECT3DDEVICE10HOOK_H_

#include "../graphics/includes.h"
#include "../hook/FW1FontWrapper.h"
#include "../hook/BeaEngine.h"
...
#endif

另外,我认为您在.h和.cpp文件中声明的变量相同是很奇怪的:

HookContext *presenthook64;
ID3D11Device *pDevice = NULL;
ID3D11DeviceContext *pContext = NULL;

DWORD_PTR* pSwapChainVtable = NULL;
DWORD_PTR* pDeviceContextVTable = NULL;

D3D11PresentHook phookD3D11Present = NULL;
D3D11DrawIndexedHook phookD3D11DrawIndexed = NULL;
D3D11ClearRenderTargetViewHook phookD3D11ClearRenderTargetView = NULL;

IFW1Factory *pFW1Factory = NULL;
IFW1FontWrapper *pFontWrapper = NULL;

bool firstTime = true;
void* detourBuffer[3];

您在头文件中定义了变量。 如果标头包含在多个翻译单元中,则当然会出现链接器错误。 就像链接程序告诉您的那样,您最终将获得同一变量的多个定义。

不要在头文件中定义变量。

如果您确实需要全局变量,那么头文件必须仅包含未定义的变量声明,例如

extern ID3D11Device *pDevice;

注意:添加了extern关键字,并删除了初始化程序。 两者都重要。

定义(带有初始化程序,如果有的话)进入实现文件

ID3D11Device *pDevice = NULL;

从到目前为止发布的内容来看,您已经将定义正确地放入了实现文件中。 剩下要做的就是通过添加extern关键字并删除初始值设定项,将标头中的定义转换为未定义的声明。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM