从.NET调用本机Win32代码(C ++ / CLI和C#)

时间:2015-12-10 18:12:56

标签: c# .net winapi visual-studio-2015 c++-cli

我正在为C#开发一个应用程序,我想使用DirectX(主要是Direct2D)作为它的图形组件。所以我正在尝试使用C ++ / CLI作为本机C ++代码和C#托管代码之间的中间层。到目前为止,在我的解决方案中有3个项目:AC #project(我不会真正讨论,因为它还没有给我任何问题),包含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在函数“private:static void __cdecl RenderWindowImpl :: InitializeWin32Class(void)”中引用(?InitializeWin32Class @ RenderWindowImpl @@ CAXXZ)wzRenderWindow d:\ documents \ visual studio 2015 \ Projects \ WizEngCS \ wzRenderWindow \ wzRenderWindowImpl.lib(RenderWindowImpl.obj)1
  4. 似乎是对C ++ / CLI不喜欢的LoadCursorW的调用,因为如果我注释掉该行,代码编译就好了。删除了Win32函数调用后,我能够从C#应用程序成功调用RenderWindow::test(),输出预期的结果为5。

    我有点失落,因为我对C ++ / CLI的理解是它非常擅长包装本机C ++类以供托管.NET应用程序使用。我真的很想理解为什么我的代码没有编译。

    作为一个相关的后续问题,我在这里咆哮错误的树吗?什么是从.NET访问DirectX方法(或类似的基于COM的C / C ++库)的传统方式?我想避免使用像SharpDX这样的第三方包装器库。

2 个答案:

答案 0 :(得分:1)

我通过将#pragma comment(lib, "User32.lib")放在RenderWindowImpl.cpp的顶部来解决问题。感谢@andlabs的修复。我不确定为什么修复问题(我以前从未需要在以前的任何项目中明确链接到user32.lib)。

答案 1 :(得分:-1)

这些不是您正在寻找的库和技术。 XNA已经包装了DirectX。你应该专门研究它。