从 .NET 调用本机 Win32 代码(C++/CLI 和 C#) [英] Calling native Win32 code from .NET (C++/CLI and C#)

查看:35
本文介绍了从 .NET 调用本机 Win32 代码(C++/CLI 和 C#)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为 C# 开发一个应用程序,我想使用 DirectX(主要是 Direct2D)作为它的图形组件.所以我尝试使用 C++/CLI 作为原生 C++ 代码和 C# 托管代码之间的中间层.到目前为止,我的解决方案中有 3 个项目:AC# 项目(我不会真正讨论它,因为它还没有给我任何问题),一个包含 Windows.h 的 C++ 静态库,以及一个用于在其他两个项目之间编组信息的动态 C++/CLI 库.到目前为止,这是我的代码:

I'm developing an app for C#, and I want to use DirectX (mostly Direct2D) for the graphical component of it. So I'm trying use use C++/CLI as an intermediary layer between the native C++ code and the managed code of C#. So far a have 3 projects in my solution: A C# project (which I won't really discuss since it's not giving me any problems yet), a C++ static library that includes Windows.h, and a dynamic C++/CLI library that's intended to marshal information between the other two projects. Here is my code so far:

在本机 C++ 项目中,我有一个名为 RenderWindowImpl 的类,因此它只包含 2 个方法:

In the native C++ project, I have a class named RenderWindowImpl that so for only contains 2 methods:

//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 的包装器:

And in my C++/CLI project, I have a class named RenderWindow that acts as a wrapper around 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();
}

当我编译我的项目时,我收到以下警告和错误:

When I compile my project, I get the following warnings and errors:

  1. Error 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. 函数private: static void __cdecl RenderWindowImpl::InitializeWin32Class(void)" (?InitializeWin32Class@RenderWindowImpl@@CAXXZ) wzRenderWindow d:\documents\visualCSProjects\Wiziz 中引用的错误 LNK2019 未解析的外部符号 __imp__LoadCursorW@8\wzRenderWindow\wzRenderWindowImpl.lib(RenderWindowImpl.obj) 1

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

It seems to be the call to LoadCursorW that C++/CLI doesn't like, as the code compiles fine if I comment out that line. With the Win32 function calls removed, I was able to successfully call RenderWindow::test() from a C# application, outputting the expected result of 5.

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

I'm a bit of a loss because my understanding of C++/CLI is that it's very good at wrapping native C++ classes for consumption by managed .NET applications. I would really like to understand why my code is not compiling.

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

As a related follow-up question, am I barking up the wrong tree here? What's the conventional way to access DirectX methods (or similar COM-based C/C++ libraries) from .NET? I'd like to avoid using 3rd-party wrapper libraries like SharpDX.

推荐答案

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

I fixed the problem by putting #pragma comment(lib, "User32.lib") at the top of my RenderWindowImpl.cpp. Thanks to @andlabs for the fix. I'm not sure why this fixed the problem (I've never needed to explicitly link to user32.lib in any of my previous projects).

这篇关于从 .NET 调用本机 Win32 代码(C++/CLI 和 C#)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆