u8it
u8it

Reputation: 4296

Unresolved Symbol Errors for C++/CLI dll in C++ Project

I am trying a very simple implementation of a C++/CLI wrapper to allow legacy C++ code to reference .Net code, as described here. I am getting stuck just trying to get my basic C++/CLI unmanaged (native) objects linked, without even including any managed/IL/.Net code.

My question is, following along with this basic setup and what I describe below, am I right to be very confused about these errors? Are there some considerations that I'm missing? Maybe the answer is that this should work, so it's not clear what's wrong. That's still helpful. A similar working example would be great.

Unresolved Symbol Errors

Error LNK2019 unresolved external symbol "__declspec(dllimport) public: __thiscall Wrapper::Test::Test(void)" (__imp_??0Test@Wrapper@@QAE@XZ) referenced in function _main NativeApp

Error LNK2019 unresolved external symbol "__declspec(dllimport) public: __thiscall Wrapper::Test::~Test(void)" (__imp_??1Test@Wrapper@@QAE@XZ) referenced in function _main NativeApp

I've reviewed related questions on SO without any luck. I've got my dll header included in the client C++ project, my project reference to the C++/CLI wrapper dll, and my define statements for import/export. My very simple code is shown below. I am not using any MFC. I am using VS2017. DumpBin.exe /exports shows export symbols that seem to match what the linker error says are missing.

      1    0 000010D0 ??0Test@Wrapper@@QAE@XZ = ??0Test@Wrapper@@QAE@XZ (public: __thiscall Wrapper::Test::Test(void))
      2    1 000010E0 ??1Test@Wrapper@@QAE@XZ = ??1Test@Wrapper@@QAE@XZ (public: __thiscall Wrapper::Test::~Test(void))
      3    2 000010C0 ??4Test@Wrapper@@QAEAAV01@ABV01@@Z = ??4Test@Wrapper@@QAEAAV01@ABV01@@Z (public: class Wrapper::Test & __thiscall Wrapper::Test::operator=(class Wrapper::Test const &))

Here's the basic code...

NativeApp.exe (project)


NativeApp.cpp (File)

#include "stdafx.h"
#include <iostream>
#include "Wrapper.h" //From additional includes directory

int main()
{
    std::cout << "Program Started" << std::endl;
    Wrapper::Test shell = Wrapper::Test::Test(); //Use dll
    std::cin.get();
    return 0;
}

Reference to Wrapper

enter image description here


Wrapper.dll (Project)


Wrapper.cpp (File)

#include "Wrapper.h"

#pragma unmanaged
namespace Wrapper {
    Test::Test() {
    }
    Test::~Test() {
    }
}

Wrapper.h (File)

#pragma once

#ifdef WRAPPER_EXPORTS  
#define WRAPPER_API __declspec(dllexport)   
#else  
#define WRAPPER_API __declspec(dllimport)   
#endif  

#pragma unmanaged
namespace Wrapper {
    class WRAPPER_API Test {
    public:
        Test();
        ~Test();
    };
}

Upvotes: 2

Views: 2055

Answers (1)

u8it
u8it

Reputation: 4296

I was under the impression that the project reference took care of any additional dependency settings behind the scenes. Apparently, that is not the case. The .lib file needed to be added as an additional dependency, as is described here. However, as described by this Microsoft document, everything worked without additional dependencies when I was using non /clr dlls, so I'm not sure why the additional dependency was only required for my CLR reference. Clearly, I need to read up on this some more.

In any case, my C++ client project requirements are listed below. I was missing the second requirement. Also, here is an example project that helped me diagnose the problem.

1.) Add project reference

enter image description here

2.) Add the .lib file as an `Additional Dependency.

enter image description here

[Optional] Use Additional Library Directories

enter image description here

3.) #include .h file in code where appropriate

enter image description here

[Optional] Use additional include directories

enter image description here

EDIT: Why the additional dependency was required, and alternative option

As noted above, I was getting hung up on why the .lib additional dependency was required for the /clr dll but not for the non-clr dll. The answer is because a /clr project is configured by default to ignore import libraries. So when the project gets referenced by another C++ project, the project reference ignores import libraries. Changing this setting (Linker > General > Ignore Import Libraries) to "No" in the /clr dll project solves the issue so that the additional dependency is not required and the project reference works the same as the non-clr C++ dll.

Upvotes: 2

Related Questions