Linker errors when calling C++/CLI code from pure C++ code - c++

I am using VS2012 and I am trying to call CLI code from C++. So I created two projects. One is executable which is pure C++ (without CLI support) and second is dynamic library which is CLI (with /clr switch). If I have main (in executable):
// main.cpp file
#include "..\CLILibrary\CCli.h"
int main()
{
Ccli test = Ccli();
test.Write();
return 0;
}
And one class in CLI library (build with CLR switch on):
// Ccli.h file
#pragma once
class Ccli
{
public:
void Write();
void CallRealCLIClass();
};
// Ccli.cpp file
#include " Ccli.h"
void Ccli::Write()
{
System::Console::WriteLine("In Ccli class.");
}
void Ccli::CallRealCLIClass()
{
// here I would like to call RealCLI class
}
Everything works fine so far. I understand, that header file (Ccli.h) cannot use anything from CLI since it has to be readable for my executable which is purely in C++ (theoretically it could if I would use something like #ifdef _MANAGED but thatÆs not my point). But in source file (Ccli.cpp) it is fine.
But now I want to use class which will be fully CLI. And I want to call it from Ccli.cpp file. So I created following class in my CLI library:
// RealCLI.h file
#pragma once
ref class RealCLI
{
public:
RealCLI(void);
System::String^ GetString();
void Write(System::String^ s);
};
// RealCLI.cpp file
#include "RealCLI.h"
RealCLI::RealCLI(void){}
System::String^ GetString()
{
System::String^ s = gcnew System::String("GetString in RealCLI class");
return s;
}
void Write(System::String^ s)
{
System::Console::WriteLine(s);
}
Now I have following problem and I don't know why. I get this error from linker:
Error 1 error LNK2020: unresolved token (06000002) RealCLI::GetString ...\RealCLI\RealCLI.obj
Error 2 error LNK2020: unresolved token (06000003) RealCLI::Write ...\RealCLI\RealCLI.obj
Error 3 error LNK1120: 2 unresolved externals ...\Debug\RealCLI.dll 1
So my library is fine (it is built without problem) but my executable have these linker errors. I don't understand why? I don't use this file in my executable project, so why is my executable even care about it? I find a way how to fix it. But since I don't know the reason why is the original program not working I consider it just as workaround. My workaround is delete RealCLI.cpp file and put everything in header file:
// RealCLI.h file
#pragma once
ref class RealCLI
{
public:
RealCLI(void) {}
// I cannot even put definition outside declaration of my class
System::String^ GetString()
{
System::String^ s = gcnew System::String("GetString in RealCLI class");
return s;
}
void Write(System::String^ s)
{
System::Console::WriteLine(s);
}
};
Why is that? What am I doing wrong? Is some of my assumptions wrong?
EDIT:
// Ccli.cpp file
#include " Ccli.h"
// !!!added this line:
#include "RealCLI.h"
void Ccli::Write()
{
System::Console::WriteLine("In Ccli class.");
}
void Ccli::CallRealCLIClass()
{
// here I would like to call RealCLI class
}
I repaired namespaces in RealCli.cpp which helped. But when I added #include "RealCLI.h" I get these error anyway:
Error 2 error LNK2020: unresolved token (06000001) RealCLI::.ctor D:\ftp\my\vyuka-cppToCLI-test\vyuka-ManagedUmanaged\UnmanagedToManagedSource.obj
Error 3 error LNK2020: unresolved token (06000002) RealCLI::GetString D:\ftp\my\vyuka-cppToCLI-test\vyuka-ManagedUmanaged\UnmanagedToManagedSource.obj
Error 4 error LNK2020: unresolved token (06000003) RealCLI::Write D:\ftp\my\vyuka-cppToCLI-test\vyuka-ManagedUmanaged\UnmanagedToManagedSource.obj
Error 5 error LNK1120: 3 unresolved externals D:\ftp\my\vyuka-cppToCLI-test\Debug\vyuka-ManagedUmanaged.exe 1

You are making basic C++ mistake. In RealCLI.cpp:
Instead of:
System::String^ GetString() { ... }
use:
System::String^ RealCLI::GetString() { ... }
Similarly for Write()

Actually I didn't set linker right. Code is (after edit) Ok. I'm linking to .obj files, because I get errors when linking directly to .dll (because it is not pure C++ but CLI). And I linked just Ccli.obj then few weeks later I add another file and forgot link RealCLI.obj...

Related

Static variable link error in MSVC even though it is created in the cpp file

I am working on a cross-platform (Linux & Windows) library. One of my class has a static member defined in the header. And I created it in a CPP file like
namespace raisim {
std::function<void()> RaiSimMsg::fatalCallback_ = []() { exit(1); };
}
The header file
#ifndef RAISIM_MESSAGE_LOGGER_HPP
#define RAISIM_MESSAGE_LOGGER_HPP
#include <chrono>
...
namespace raisim {
class RaiSimMsg {
public:
...
void stream(const char *file, const int line, std::stringstream &msg, int severity) {
if (severity == RSEVERITY_FATAL)
fatalCallback_();
}
private:
static std::function<void()> fatalCallback_;
};
}
#endif //RAISIM_MESSAGE_LOGGER_HPP
This works perfectly with GCC and Clang in Linux. But MSVC is giving a link error. Does MSVC have its own rules for static members??
Full error log
1>anymal.obj : error LNK2001: unresolved external symbol "private: static class std::function<void __cdecl(void)> raisim::RaiSimMsg::fatalCallback_" (?fatalCallback_#RaiSimMsg#raisim##0V?$function#$$A6AXXZ#std##A)
1>C:\Users\ultrafrog\source\repos\raisim\build\benchmark\Debug\speed_test_anymal.exe : fatal error LNK1120: 1 unresolved externals
1>Done building project "speed_test_anymal.vcxproj" -- FAILED.
Jack Dingler's answer here
https://www.codeproject.com/Questions/585271/Aplusstaticplusmemberplusvariableplusexportpluserr
worked. So the issue is that the Windows linker needs to know that if it has to import or export the symbol. So we have to declare __declspec(dllexport) when we export (when we build the library) and __declspec(dllimport) for using it. We can switch that using a compilation flag. I am not sure why they designed the linker like this but anyway it works now.

Unresolved external symbol when putting definition in CPP file

For the life of me I cannot figure out what is causing this... I keep getting unresolved external symbol error. However, if I put an empty definition in the header file it compiles correctly.
WINMAIN.CPP
#include "FILE_XXX.H"
int WINMAIN WinMain(...)
{
EnableOpenTest(); // call like this
return 0;
}
FILE_WORKS_CORRECTLY.H
#ifndef _FILE_WORKS_CORRECTLY_
#define _FILE_WORKS_CORRECTLY_
void EnableOpenTest() { }
#endif
However, when I do something like this (correctly), it does not work and I get a compile-time error.
FILE_DOES_NOT_WORK_CORRECTLY.H
#ifndef _FILE_DOES_NOT_WORK_CORRECTLY_
#define _FILE_DOES_NOT_WORK_CORRECTLY_
void EnableOpenTest();
#endif
FILE_DOES_NOT_WORK_CORRECTLY.CPP
#include "FILE_DOES_NOT_WORK_CORRECTLY.H"
void EnableOpenTest() { /* do work here */ }
UPDATE:
Upon further investigation, I found the issue has to do with me having multiple projects in the same solution. I then try to reference a function in one project from another project. Obviously I'm doing this incorrectly.
The only mistake i see is that in the cpp file you need to include the return type as well. It should be
void EnableOpenTest()
{
//Enter Code Here
}
Inside of FILE_DOES_NOT_WORK_CORRECTLY.CPP:
EnableOpenTest(){ /* do work here */ }
must be
void EnableOpenTest(){ /* do work here */ }
Looks like your compiler sets the missing return type to int instead of yelling at you with a error message.
You should turn on compiler warnings, it would allow you to notice such errors very quickly.
Also, inside of FILE_WORKS_CORRECTLY.H you have another error:
void EnableOpenTest() { }
must be
inline void EnableOpenTest() { }
Otherwise it will trigger a error message if this header is included twice (i.e. in more that one .cpp file).
Solved it!
Additional projects needed to be static library (main project .exe)
Added References of library projects to main project
Obviously the file structure caused a lot of these issues.

Linking failure within solution

EDIT: I know there are similar questions, but I cannot find an answer to a following issue: Why the methods inside the class are working correctly and outside are not.
I've got a weird problem in my project which I'm developing in MSVC++ 2012. My project consists of different modules of code. The important modules from the problem's point of view is a library and the GUI. They exist as different projects in the same solution.
I have some methods in the library which are part of the classes (in this case Calibration3D):
void Calibration3D::load(const std::string &path)
I use it without problems when I need it in the GUI, however I need to use a following method (outside the class):
void xxxyyy()
But when I'm trying to use that function (outside the class but in the same namespace) I get a following error:
1>project_xml.obj : error LNK2001: unresolved external symbol "void __cdecl cci::xxxyyy(void)" (?xxxyyy#cci##YAXXZ) 1>D:\praca_pw\cci\build-msvc2012\x64\Release\\ccigui.exe : fatal error LNK1120: 1 unresolved externals
Anybody knows how to solve it?
When I have a header file like this:
namespace xyz {
void foo();
class bar { ... };
}
then I write the cpp file like this:
#include "xyz.h"
namespace xyz {
void foo() { ... }
bar::bar() { ... }
}
This means I have to type a lot less and make fewer mistakes with regard to namespaces.
OK, solved, it seems that when a method is defined inside the namespace in header file, it should also be defined explicitly as part of namespace in implementation file, in this case:
cci::xxxyyy()
{
...
}
will work and
xxxyyy()
{
...
}
will not.

unresolved external symbol in c++ with MS visual studio 9

My code will be similar to the below code:
class DMLGroup
{
public:
DMLGroup();
~DMLGroup();
void SetName(string name);
private:
string mName;
};
void DMLGroup::SetName(string nm){
mName.assign( nm );
}
int main()
{
string api="API_DML";
DMLGroup * dmlGr = new DMLGroup();
dmlGr->SetName(api.c_str()); //Getting link error with this statement
}
I could able to compile the above code but failed to link using MS visual studio 9 on windows 7 32-bit OS.
Note: I am able to compile, link and run successfully on suselinux-x8664 platform. The problem is only with windows
Please tell me how to resolve this?
The following code compiles & links fine:
#include "stdafx.h"
#include <string>
class DMLGroup
{
public:
DMLGroup() {}
~DMLGroup(){}
void SetName(std::string name);
private:
std::string mName;
};
void DMLGroup::SetName(std::string nm){
mName.assign( nm );
}
int main()
{
std::string api="API_DML";
DMLGroup * dmlGr = new DMLGroup();
dmlGr->SetName(api.c_str()); //Getting link error with this statement
}
What I changed:
#included stdafx.h because it's VS standard - you can turn it off
#includes because it was missing
decorated every use of string with std:: - because most probably you'll use your class definition in a header file and there you simply don't use "using namespace"
supplied default implementation for constructor & destructor
That's all. Check what from the above part is missing or supply an example that exposes the problem & supply the linker error message.

Compiler Error __ZTVN13..6..E

I'm currently struggeling with a compilerproblem. The problem is, that i use one of the MoSync example apps called "European Countries" (written in c++) to write my own. But when i compile the modified code, it gives me following error in response:
Controller.cpp:24: Error: Unresolved symbol '__ZTVN13Flightmanager6FlightE',
I already had a look at the example several times and i already copied the code from the example to mine, but it doesn't solve any problems.
In paticutlar i might understand what the error means (i do have c experience), but i've never seen such structured error. I also looked at namespacing conventions but there shouldn't be any problems.
//Flight.h
namespace Flightmanager
{
class Flight
{
public:
static int flightCounter;
/**
* The constructor creates the user interface.
*/
Flight(char *flightnumber, char *gate, char *departure, char *additionalinfo, char *destinationairport, char *destinationairportshort) {
this->_id = flightCounter;
flightCounter ++;
this->_flightnumber = flightnumber;
this->_gate = gate;
this->_departure = departure;
this->_additionalinfo = additionalinfo;
this->_destinationairport = destinationairport;
this->_destinationairportshort = destinationairportshort;
}
virtual ~Flight();
}
//Controller.h
#include [all other includes]
#include "../Model/Flight.h"
namespace Flightmanager
{
Controller::Controller():
mFlightArray(NULL),
mCurrentlyShownScreen(NULL)
{
initScreenSizeConstants();
initPlatformType();
//error: Unresolved symbol '__TZVN13Flightmanager6FlightE'.
initData();
//error: Unresoled symbol '__TZVN13Flightmanager6Flight13flightCounterE'.
mFlightTableView = new TableViewController(*this);//error: Unresoled symbol '__TZVN13Flightmanager6Flight13flightCounterE'.
mFlightDetailView = new DetailViewController();
}
}
I use MoSync Version 3.2
Build date: 121219-1556
Thx
You need to link in something that has definitions for:
Flight::flightCounter
Flight::~Flight()
whether that's a .o object file for Flight.cpp (or some source file) or a library depends on your project.