【问题标题】:Calling native Win32 code from .NET (C++/CLI and C#)从 .NET(C++/CLI 和 C#)调用本机 Win32 代码
【发布时间】:2015-12-10 18:12:56
【问题描述】:

我正在为 C# 开发一个应用程序,我想使用 DirectX(主要是 Direct2D)作为它的图形组件。所以我尝试使用 C++/CLI 作为原生 C++ 代码和 C# 托管代码之间的中间层。到目前为止,我的解决方案中有 3 个项目:一个 C# 项目(我不会真正讨论它,因为它还没有给我带来任何问题)、一个包含 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 unresolved externals 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

这似乎是 C++/CLI 不喜欢的对 LoadCursorW 的调用,因为如果我注释掉该行,代码编译得很好。删除 Win32 函数调用后,我能够从 C# 应用程序成功调用 RenderWindow::test(),输出预期结果 5。

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

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

【问题讨论】:

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


【解决方案1】:

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

【讨论】:

  • 总是必须明确链接到您的应用程序正在使用的任何库。碰巧的是,本地应用程序的 New Project 向导已经将 user32.lib(和其他几个)添加到链接器输入中。显然,Visual Studio does rot the mind.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-03
  • 1970-01-01
  • 1970-01-01
  • 2013-05-08
  • 2015-03-13
相关资源
最近更新 更多