Reputation: 4296
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.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
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
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
2.) Add the .lib file as an `Additional Dependency.
[Optional] Use Additional Library Directories
3.) #include
.h file in code where appropriate
[Optional] Use additional include directories
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