我尝试构建自己的 Direct2D 库,但在尝试使用它时出现很多链接器错误

I tried to build my own Direct2D library, but I get lots of linker errors upon trying to use it

提问人:SetupWizard 提问时间:7/3/2022 更新时间:7/3/2022 访问量:103

问:

我编写了一个使用 Direct2D 的静态库。它编译得很好,没有警告;但是当我尝试在示例项目中实现它时,我得到了大量的链接器错误:

Severity    Code    Description Project File    Line    Suppression State
Error   LNK2019 unresolved external symbol __imp_TranslateMessage referenced in function "private: int __cdecl Ice2D::Ice2DApp::ProcessMessages(void)" (?ProcessMessages@Ice2DApp@Ice2D@@AEAAHXZ)   Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK2019 unresolved external symbol __imp_DispatchMessageW referenced in function "private: int __cdecl Ice2D::Ice2DApp::ProcessMessages(void)" (?ProcessMessages@Ice2DApp@Ice2D@@AEAAHXZ)   Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK2019 unresolved external symbol __imp_PeekMessageW referenced in function "private: int __cdecl Ice2D::Ice2DApp::ProcessMessages(void)" (?ProcessMessages@Ice2DApp@Ice2D@@AEAAHXZ)   Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK2019 unresolved external symbol __imp_DefWindowProcW referenced in function "private: __int64 __cdecl Ice2D::Ice2DApp::HandleMsg(struct HWND__ *,unsigned int,unsigned __int64,__int64)" (?HandleMsg@Ice2DApp@Ice2D@@AEAA_JPEAUHWND__@@I_K_J@Z)  Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK2019 unresolved external symbol __imp_PostQuitMessage referenced in function "private: __int64 __cdecl Ice2D::Ice2DApp::HandleMsg(struct HWND__ *,unsigned int,unsigned __int64,__int64)" (?HandleMsg@Ice2DApp@Ice2D@@AEAA_JPEAUHWND__@@I_K_J@Z) Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK2019 unresolved external symbol __imp_RegisterClassExW referenced in function "public: long __cdecl Ice2D::Ice2DApp::Initialize(void)" (?Initialize@Ice2DApp@Ice2D@@QEAAJXZ) Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK2019 unresolved external symbol __imp_CreateWindowExW referenced in function "public: long __cdecl Ice2D::Ice2DApp::Initialize(void)" (?Initialize@Ice2DApp@Ice2D@@QEAAJXZ)  Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK2019 unresolved external symbol __imp_ShowWindow referenced in function "public: long __cdecl Ice2D::Ice2DApp::Initialize(void)" (?Initialize@Ice2DApp@Ice2D@@QEAAJXZ)   Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK2019 unresolved external symbol __imp_SetCapture referenced in function "private: __int64 __cdecl Ice2D::Ice2DApp::HandleMsg(struct HWND__ *,unsigned int,unsigned __int64,__int64)" (?HandleMsg@Ice2DApp@Ice2D@@AEAA_JPEAUHWND__@@I_K_J@Z)  Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK2019 unresolved external symbol __imp_ReleaseCapture referenced in function "private: __int64 __cdecl Ice2D::Ice2DApp::HandleMsg(struct HWND__ *,unsigned int,unsigned __int64,__int64)" (?HandleMsg@Ice2DApp@Ice2D@@AEAA_JPEAUHWND__@@I_K_J@Z)  Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK2019 unresolved external symbol __imp_UpdateWindow referenced in function "public: long __cdecl Ice2D::Ice2DApp::Initialize(void)" (?Initialize@Ice2DApp@Ice2D@@QEAAJXZ) Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK2019 unresolved external symbol __imp_SetForegroundWindow referenced in function "private: __int64 __cdecl Ice2D::Ice2DApp::HandleMsg(struct HWND__ *,unsigned int,unsigned __int64,__int64)" (?HandleMsg@Ice2DApp@Ice2D@@AEAA_JPEAUHWND__@@I_K_J@Z) Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK2019 unresolved external symbol __imp_SetWindowTextW referenced in function "protected: void __cdecl Ice2D::Ice2DApp::SetWindowTitle(class std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class std::allocator<wchar_t> >)" (?SetWindowTitle@Ice2DApp@Ice2D@@IEAAXV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@Z)   Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK2019 unresolved external symbol __imp_GetClientRect referenced in function "private: long __cdecl Ice2D::Ice2DApp::CreateDeviceResources(void)" (?CreateDeviceResources@Ice2DApp@Ice2D@@AEAAJXZ) Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK2019 unresolved external symbol __imp_AdjustWindowRect referenced in function "public: long __cdecl Ice2D::Ice2DApp::Initialize(void)" (?Initialize@Ice2DApp@Ice2D@@QEAAJXZ) Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK2019 unresolved external symbol __imp_GetWindowLongPtrW referenced in function "private: __int64 __cdecl Ice2D::Ice2DApp::HandleMsg(struct HWND__ *,unsigned int,unsigned __int64,__int64)" (?HandleMsg@Ice2DApp@Ice2D@@AEAA_JPEAUHWND__@@I_K_J@Z)   Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK2019 unresolved external symbol __imp_SetWindowLongPtrW referenced in function "private: __int64 __cdecl Ice2D::Ice2DApp::HandleMsg(struct HWND__ *,unsigned int,unsigned __int64,__int64)" (?HandleMsg@Ice2DApp@Ice2D@@AEAA_JPEAUHWND__@@I_K_J@Z)   Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK2019 unresolved external symbol __imp_LoadCursorW referenced in function "public: long __cdecl Ice2D::Ice2DApp::Initialize(void)" (?Initialize@Ice2DApp@Ice2D@@QEAAJXZ)  Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\Ice2D.lib(Ice2DApp.obj)    1   
Error   LNK1120 18 unresolved externals Ice2D_Sample    C:\Users\jkjt1\source\repos\C++\Ice2D_Sample\x64\Debug\Ice2D_Sample.exe 1   

此外,如果我在不将其设为库的情况下使用代码(即将所有源文件复制到项目中),它就可以正常工作。我尝试编译的示例项目相当简单,只有一个 .cpp 文件:

#include <Ice2DApp.h>

class SampleApp : public Ice2D::Ice2DApp
{
public:
    void Settings() override;
    void Setup() override;
    void Update() override;
    void Draw() override;
private:
    Ice2D::TextFormat font1;
    Ice2D::LinearBrush linBrush;
    Ice2D::RadialBrush radBrush;
    unsigned short int fps;
};

void SampleApp::Settings()
{
    // Settings for window creation
    SetWindowTitle(L"Sample Ice2D Window");
    SetWindowSize(600, 300);
}

void SampleApp::Setup()
{
    // Fill pointers and initialize game logic
    CreateTextFomat(L"arial", 36.0f, font1);
    Ice2D::GradientStop linStops[3] =
    {
        {0.0f, Ice2D::Color(Ice2D::Color::Red)},
        {0.5f, Ice2D::Color(Ice2D::Color::Yellow)},
        {1.0f, Ice2D::Color(Ice2D::Color::Green)}
    };
    Ice2D::GradientStop radStops[2] =
    {
        {0.0f, Ice2D::Color(Ice2D::Color::Yellow)},
        {1.0f, Ice2D::Color(Ice2D::Color::Purple)}
    };
    CreateLinearBrush(linStops, 3u, linBrush, { 10, 150 }, { 254, 150 });
    CreateRadialBrush(radStops, 2u, radBrush, { 0, 0 }, { 0, 0 }, { 30, 30 });
    SetLinearBrush(linBrush);
    SetRadialBrush(radBrush);
}

void SampleApp::Update()
{
    // Update game logic
    if (FrameCount() % 60 == 0)
    {
        fps = (unsigned short int)(1.0f / DeltaTime());
        SetTextColor(fps <= 60 ? Ice2D::Color::Red : Ice2D::Color::Black);
    }
    radBrush->SetCenter(MakePoint(mouse.GetPos()));
}

void SampleApp::Draw()
{
    // Execute Draw Commands
    BeginDraw();
    Clear(Ice2D::Color::CornflowerBlue);
    FillRect(10, 100, fps * 2 + 10, 200, BrushMode::Linear);
    DrawRect(10, 100, 500, 200, 2.0f);
    FillEllipse(MakePoint(mouse.GetPos()), 30, 30, BrushMode::Radial);
    RenderText(L"FPS: " + std::to_wstring(fps), font1, 10, 10, 300, 50);
    EndDraw();
}

int WINAPI WinMain(
    HINSTANCE /* hInstance */,
    HINSTANCE /* hPrevInstance */,
    LPSTR /* lpCmdLine */,
    int /* nCmdShow */)
{
    HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);

    if (SUCCEEDED(CoInitialize(NULL)))
    {
        SampleApp app1;

        if (SUCCEEDED(app1.Initialize()))
        {
            app1.Start();
        }
        CoUninitialize();
    }

    return 0;
}

我认为问题出在我如何编译它或如何将其包含在示例项目中。我确保它们使用相同的编译器版本和运行时库。我尝试过动态链接,但这给了我一整套其他问题(.dll文件已损坏)。顺便说一句,我正在使用 Visual Studio 2022。

C++ Visual-Studio 链接器错误 Direct2D

评论

2赞 jkb 7/3/2022
这些似乎是 Win32 函数。您是否链接到适当的库,例如 kernel32.lib?
1赞 Aganju 7/3/2022
构建库时,需要将要从外部使用的所有符号(函数、变量)标记为外部/导出。我不知道具体是怎么回事;这是一些神奇的宏,你要么知道,要么迷路了。我花了很多时间试图解决这个问题。
0赞 SetupWizard 7/3/2022
@jkb 我过去在使用 Win32 时从未这样做过。那会在哪里(顺便说一句,我在 Windows 上)。
0赞 SetupWizard 7/3/2022
@Aganju 我是否必须将“extern”关键字添加到所有函数中?
1赞 Aganju 7/3/2022
不,它更复杂,因为链接器需要处理它,而不是编译器。类似的东西。如果我知道,我会写一个答案。__dll_export(...)

答:

0赞 SetupWizard 7/3/2022 #1

对于遇到相同问题的其他任何人(并且不介意切换到动态链接的库),我通过在示例项目中添加我需要访问的任何函数来解决这个问题。我使用宏来执行此操作:.__declspec(dllexport)#define ICE2D_API __declspec(dllexport)

评论

0赞 Minxin Yu - MSFT 7/26/2022
嗨,很高兴知道您已经找到了解决此问题的解决方案!请考虑将其接受为答案,以将其状态更改为“已回答”。只是一个提醒:)