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
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();
};
}
__declspec(dllexport)
is not used by C++/CLI and does not generate the .NET metadata needed by C#.#pragma unmanaged
results in things that can only be accessed by other C++ code (it is possible for that other C++ code to be seen from C#). To make C#-usable objects, you need to usepublic ref class
on the C++/CLI side. – Ben Voigt#pragma unmanaged
code can't use .NET stuff, it can only call other C++ code (that C++ code can use#pragma managed
and .NET). For what you describe (wrapping calls to C# inside a main application written in C++) there's no reason to use a DLL. Just link the C++ and C++/CLI files together into the EXE. – Ben Voigt__declspec
stuff, and change the project reference to "link library dependencies", your sharing of native C++ objects should start working. – Ben Voigt