0

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:

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);
}

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. Warning LNK4075 ignoring '/EDITANDCONTINUE' due to '/OPT:LBR' specification wzRenderWindow d:\documents\visual studio 2015\Projects\WizEngCS\wzRenderWindow\wzRenderWindowImpl.lib(RenderWindowImpl.obj) 1
  3. Error LNK2019 unresolved external symbol __imp__LoadCursorW@8 referenced in function "private: static void __cdecl RenderWindowImpl::InitializeWin32Class(void)" (?InitializeWin32Class@RenderWindowImpl@@CAXXZ) wzRenderWindow d:\documents\visual studio 2015\Projects\WizEngCS\wzRenderWindow\wzRenderWindowImpl.lib(RenderWindowImpl.obj) 1

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.

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.

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.

C. Finegan
  • 83
  • 6
  • Possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – IInspectable Dec 10 '15 at 21:44

1 Answers1

1

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).

Bondolin
  • 2,793
  • 7
  • 34
  • 62
C. Finegan
  • 83
  • 6
  • 2
    You **always** have to explicitly link against any library your application is using. It just so happens, that the *New Project* wizard for native applications already adds *user32.lib* (and several others) to the linker input. Apparently, [Visual Studio does rot the mind](http://charlespetzold.com/etc/DoesVisualStudioRotTheMind.html). – IInspectable Dec 10 '15 at 21:42