簡體   English   中英

從.NET(C ++ / CLI和C#)調用本機Win32代碼

[英]Calling native Win32 code from .NET (C++/CLI and C#)

我正在為C#開發一個應用程序,並且想將DirectX(主要是Direct2D)用於其圖形組件。 因此,我嘗試使用C ++ / CLI作為本機C ++代碼和C#托管代碼之間的中間層。 到目前為止,我的解決方案中有3個項目:AC#項目(由於它還沒有給我帶來任何問題,所以我將不進行討論),一個包含Windows.h的C ++靜態庫以及一個旨在供使用的動態C ++ / CLI庫在其他兩個項目之間封送信息。 到目前為止,這是我的代碼:

在本機C ++項目中,我有一個名為RenderWindowImpl的類,因此僅包含2個方法:

//RenderWindowImpl.h
#pragma once

#include <Windows.h>

class RenderWindowImpl final
{
public:
    RenderWindowImpl() = default;
    ~RenderWindowImpl() = default;

    int test();

private:
    static void InitializeWin32Class();
};

// RenderWindowImpl.cpp
#include "RenderWindowImpl.h"

int RenderWindowImpl::test()
{
    return 5;
}

void RenderWindowImpl::InitializeWin32Class()
{
    WNDCLASSEXW wc = { 0 };

    wc.cbSize = sizeof(WNDCLASSEXW);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = nullptr;
    wc.hInstance = GetModuleHandleW(0);
    wc.hCursor = LoadCursorW(nullptr, IDC_ARROW);
    //wc.lpszClassName = L"wz.1RenderWindowImpl";

    //// TODO: error check
    //RegisterClassExW(&wc);
}

而在我的C ++ / CLI的項目,我有一個類名為RenderWindow充當周圍的包裝RenderWindowImpl

// wzRenderWindow.h
#pragma once

//#pragma managed(push, off)
#include "RenderWindowImpl.h"
//#pragma managed(pop)

using namespace System;

namespace wzRenderWindow {

    public ref class RenderWindow sealed
    {
    public:
        RenderWindow();
        ~RenderWindow();

        int test();

    private:
        RenderWindowImpl* impl;
    };
}

// wzRenderWindow.h.
#include "stdafx.h"
#include "wzRenderWindow.h"

wzRenderWindow::RenderWindow::RenderWindow()
{
    // Initialize unmanaged resource
    impl = new RenderWindowImpl();

    try
    {
        // Any factory logic can go here
    }

    catch (...)
    {
        // Catch any exception and avoid memory leak
        delete impl;
        throw;
    }
}

wzRenderWindow::RenderWindow::~RenderWindow()
{
    // Delete unmanaged resource
    delete impl;
}

int wzRenderWindow::RenderWindow::test()
{
    return impl->test();
}

編譯項目時,出現以下警告和錯誤:

  1. 錯誤LNK1120 1無法解析的外部wzRenderWindow d:\\ documents \\ visual studio 2015 \\ Projects \\ WizEngCS \\ Debug \\ wzRenderWindow.dll 1
  2. 警告LNK4075由於'/ OPT:LBR'規范而忽略了'/ EDITANDCONTINUE'wzRenderWindow d:\\ documents \\ visual studio 2015 \\ Projects \\ WizEngCS \\ wzRenderWindow \\ wzRenderWindowImpl.lib(RenderWindowImpl.obj)1
  3. 錯誤LNK2019無法解析的外部符號__imp__LoadCursorW @ 8在函數“私有:靜態void __cdecl RenderWindowImpl :: InitializeWin32Class(void)”中引用(?InitializeWin32Class @ RenderWindowImpl @@ CAXXZ)wzRenderWindow d:\\ documents \\ Visual Studio 2015 \\ Projects \\ Wz wzRenderWindowImpl.lib(RenderWindowImpl.obj)1

這似乎是C ++ / CLI不喜歡的對LoadCursorW的調用,因為如果我注釋掉那行,代碼可以很好地編譯。 刪除Win32函數調用后,我能夠從C#應用程序成功調用RenderWindow::test() ,輸出預期結果5。

我有點不知所措,因為我對C ++ / CLI的理解是,它非常擅長包裝本機C ++類以供托管.NET應用程序使用。 我真的很想了解為什么我的代碼沒有編譯。

作為相關的后續問題,我是否在這里樹錯了樹? 從.NET訪問DirectX方法(或類似的基於COM的C / C ++庫)的常規方法是什么? 我想避免使用SharpShar等第三方包裝器庫。

我通過將#pragma comment(lib, "User32.lib")放在我的RenderWindowImpl.cpp的頂部來解決了該問題。 感謝@andlabs提供此修復程序。 我不確定為什么要解決此問題(我以前的任何項目中都不需要顯式鏈接到user32.lib)。

這些不是您要查找的庫和技術。 XNA已經包裝DirectX。 您應該專門研究使用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM