Linker error when calling function in native C++ from a c++/cli project - c++-cli

I am trying to call functions in c++ from C# and to do this, I created a C++/CLI project to wrap C++ codes.
My code compiles, but during linkage, I am getting error that linker can not find methods which are defined in c++ code.
The c++ code is a static library and I add a reference to it in C++/CLI project (common properties -> framework and references -> add new reference)
My questions:
Is there anything else should I do?
is adding reference in this sections means that the reference is a .net assembly? Or could it be a reference to a static library.
Edit 1
I am sing VS 2012 on windows 7 64bit
Linker Error:
Error 3 error LNK2019: unresolved external symbol "public: static class MyFile __cdecl MyFile::ReadMyFile(char *)" (?ReadMyFile#MyFile##$$FSA?AV1#PAD#Z) referenced in function "public: static class MyFileWrapper::MyFileWrapper ^ __clrcall MyFileWrapper::MyFileWrapper::ReadMyFile(class System::String ^)" (?ReadMyFile#MyFileWrapper#1#$$FSMP$AAV11#P$AAVString#System###Z) MyFileWrapper.obj

You didn't post the linker error message, that makes it difficult to answer this question accurately. The most common causes:
Forgetting to tell the compiler that the function is a native function and not a managed one. You can tell from the linker error message when you see it using the __clrcall calling convention, native code normally uses the __cdecl calling convention. You fix that by putting #pragma managed(push, off) before the #include, #pragma managed(pop) after it.
Trying to link a static library that was compiled with /clr in effect. That's not supported without otherwise drawing a complaint about that when you build the library, unfortunately. The equivalent is already well supported by the CLR, it binds libraries at runtime. You fix that by creating a class library project instead so you'll get a DLL after building it. Use Add Reference to import the declarations from that assembly instead of using #include.
Forgetting to tell the linker that it needs to link an unmanaged static library or import library. Using Add Reference is supported in VS2010 and up, on earlier versions of VS you need to use the Linker, Input, Additional Dependencies setting or use #pragma comment(lib, "name") in your source code.

$$F part of the given mangled name is a marker of function modifier , that means managed function [Managed C++ or C++/CLI], according to "Visual C++ name mangling".
I faced very similar problem. I figured out that in my case there was:
<ProjectReference Include="ProjName\ProjName.vcxproj">
<ProjectReference Include="..\ProjName\ProjName.vcxproj">
I've just fixed that and made rebuild and it helped me.

Related

Using Standard C++ libraries in a C++/CLI project (calculating median)

I've a C++/CLI project and I would need to compute the median on arrays (as fast as possible). I've found here a solution, but when I try it in my C++/CLI project I get the following error:
error LNK2019: unresolved external symbol _CrtDbgReportW referenced in function "public: short & __cdecl std::vector<short,class std::allocator<short> >::operator[](unsigned __int64)"
Is this due to the fact that I'm compiling in /MD? If yes and since it seems that /clr and /MT cannot be combined, what I should use? Any suggestion?
The credit goes to Hans Passant, however I reply in case somebody else would experience the same. In my C++/ClI project under Properties>C/C++>Code Generation>Runtime Library, while being in DEBUG mode I had /MD instead than /MDd.

Including headers from an unmanaged C++ code inside C++/CLI code

I'm writing a CLR wrapper for an unmanaged C++ library.
There are two files I'm including from the unmanaged lib:
//MyCLIWrapper.h
#include "C:\PATH\TO\UNMANAGED\Header.h"
#include "C:\PATH\TO\UNMANAGED\Body.cpp"
Then I'm writing CLI implementations for the unmanaged library functions:
//MyCLIWrapper.h
// includes ...
void MyCLIWrapper::ManagedFunction()
{
UnmanagedFunction(); // this function is called successfuly
}
However, if my Unmanaged function contains calls to other functions that are defined in other unmanaged header files. This causes a compiler linkage error.
If I add includes to the unmanaged headers that define these functions, my errors get resolved. However, there is a lot of functions, and a lot of includes required.
Is there a different way to approach this?
EDIT:
P.S.
My managed code is in a separate Visual Studio project (output - DLL), and the compile settings are set to /CLR. Unmanaged code is in a separate Win32 project (output - DLL).
Also, after more research I concluded that theoretically I could set my Win32 unmanaged project to CLR and just add my managed classes and headers in there as an entry point, and then it would all compile into a single DLL file. That would probably solve (?) the linkage errors. However, I would prefer to preserve the loose coupling as well as the additional series of problems that can raise from setting my unmanaged project to CLR.
EDIT #2:
The unmanaged class that I'm referencing (body.cpp, header.h) contains includes to the required files that define the functions that are causing the problems. However, my managed code doesn't pick up on the includes that are in the unmanaged body.cpp and header.h.
Linker errors are a different kettle of fish from compiler errors. You forgot to document the exact linker errors you see, but a very common mishap when you compile code with /clr in effect is that the default calling convention for non-C++ member function changes. The default is __clrcall, a convention that's optimized for managed code. While functions compiled without /clr defaults to __cdecl. Which changes the way the function name is mangled. You see this back in the linker error message, is shows that it is looking for a __clrcall function and can't find it.
You'll need to either explicitly declare your functions in the .h file with __cdecl. Or tell the compiler that these functions are not managed code. Which is the best way to tackle it:
#pragma managed(push, off)
#include "unmanagedHeader.h"
#pragma managed(pop)
Solution was fairly simple:
I added both unmanaged and managed projects to a single solution in Visual Studio.
Set the unmanaged project's "Configuration Type" to "Static Library" (.lib).
Right click on the managed project -> References -> Add Reference -> Projects -> -> Add Reference.
Then in my managed class, I include the header.h (only) just like I did in my question.
Compiled successfully!
Thank you

Errors using the glut library with C++/CLI

I've been using OpenGL with glut for quite a while now and have never encountered this issue.
I've been trying to include the glut library in my c++/cli project for the use of it's library functions like glutMouseFunc etc. My project already uses gl.h and glu.h. However the moment I include:
#include <gl/glut.h>
I get the following string of error messages.
1>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\gl/glut.h(490): error C3641: 'glutInit_ATEXIT_HACK' : invalid calling convention '__stdcall ' for function compiled with /clr:pure or /clr:safe
1>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\gl/glut.h(490): error C2664: '__glutInitWithExit' : cannot convert parameter 3 from 'void (__cdecl *)(int)' to 'void (__cdecl *)(int)'
1> Address of a function yields __clrcall calling convention in /clr:pure and /clr:safe; consider using __clrcall in target type
1>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\gl/glut.h(507): error C3641: 'glutCreateWindow_ATEXIT_HACK' : invalid calling convention '__stdcall ' for function compiled with /clr:pure or /clr:safe
1>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\gl/glut.h(507): error C2664: '__glutCreateWindowWithExit' : cannot convert parameter 2 from 'void (__cdecl *)(int)' to 'void (__cdecl *)(int)'
1> Address of a function yields __clrcall calling convention in /clr:pure and /clr:safe; consider using __clrcall in target type
1>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\gl/glut.h(553): error C3641: 'glutCreateMenu_ATEXIT_HACK' : invalid calling convention '__stdcall ' for function compiled with /clr:pure or /clr:safe
1>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\gl/glut.h(553): error C2664: '__glutCreateMenuWithExit' : cannot convert parameter 2 from 'void (__cdecl *)(int)' to 'void (__cdecl *)(int)'
1> Address of a function yields __clrcall calling convention in /clr:pure and /clr:safe; consider using __clrcall in target type
I've read in a few other places that similar problems have been solved by switching the clr support in the project's properties (properties>configuration properties>general>common language runtime support) to anything that's not clr:safe or clr:pure.
I've in fact tried compiling with all 4 available versions of clr support:
Common Language runtime support (/clr)
Pure MSIL Common Language Runtime Support (/clr:pure)
Safe MSIL Common Language Runtime Support (/clr:safe)
Common Language Runtime Support, Old Syntax (/clr:oldSyntax)
However I still receive the same error message. I've no idea where this issue comes from. I've used glut in other projects (c++ only), and never encountered this problem until i started using c++/cli.
Any insight into what this could be would be greatly appreciated.
Thanks in advance,
Guy
(By the way, I'm using Visual Studio 2010 if it turns out to be of any relevance.)
The error message you're displaying will not occur if using /clr to compile a file, only /clr:pure or /clr:safe.
You definitely need to use /clr, and not use /clr:pure or /clr:safe, as the latter flags will not allow you to use native code at all within the .cpp file. Make sure you don't have a single file overriding the project settings for /clr, either, as this can cause the compiler to create errors such as you're displaying for those files.
You'll need to let the compiler know that glut.h is a header for unmanaged code. If it doesn't know then it will assume that is contains managed functions and it doesn't like what it sees. You do so like this:
#pragma managed(push, off)
#include <gl/glut.h>
#pragma managed(pop)
A more general way to keep out of trouble like this is by strictly separating the C++/CLI code from the native code. You can turn on the /clr option for individual source files, it doesn't need to be turned on for every source code file in your project. This also helps to get native code compiled to machine code instead of IL, it is faster that way.

c++/cli interface header file

I have a C++ project (visual studio 2010) which consists of native code and c++/cli code as well. I cant compile the whole project with /clr, so I just do it for the respective c++/cli files. My Problem is that a header file cant be compiled with /clr, but I want to make some c++/cli functions reusable within the whole project and therefor define the method prototypes in a header file to include it in every file where I need it. Is there a solution? I have tried to define some mixed code method prototypes in a header file, but /clr must be switched on for that to compile.
Here is my example:
Test.h
#include <Windows.h>
#include <vector>
#include <string>
using std::vector;
using std::string;
#include <msclr/marshal.h>
#pragma managed
using namespace msclr::interop;
using namespace System;
using namespace System::IO;
using namespace System::Runtime::InteropServices;
public ref class Test
{
public:
int Foo();
};
Test.cpp
#include "Test.h"
int Test::Foo()
{
return 4;
}
Intellisense is complaining with errors in Test.h like c++/cli must be enabled to use #using. But I think this is negligible and it would compile anyway.
Compilation aborts with a Linker Error (sry, i have german VS version)
Fehler 6 error LNK1255: Fehler bei Verknüpfung aufgrund von Metadatenfehlern.
Fehler 4 error LNK2022: Fehler bei Metadatenoperation (8013118D) : Duplizierte Typen (_PROPSHEETPAGEA) wurden gefunden, aber die Typenlayoutinformationen sind nicht konsistent: (0x02000198).
Fehler 5 error LNK2022: Fehler bei Metadatenoperation (8013118D) : Duplizierte Typen (_PROPSHEETPAGEW) wurden gefunden, aber die Typenlayoutinformationen sind nicht konsistent: (0x020001d1).
I definitely dont have a duplicate class "Test" elsewhere, so I dont know where the duplicate comes from. What are typelayout informations and why are they not consistent?
I think you've all missed the point.
You can easily compile a native project with some /clr classes. (For example: A native DLL will still function like a native DLL, however, it can also be loaded into C#, and it's /clr compiled classes can then be accessed in C#.)
That's why such an option exist at the file level. (Right click .cpp: Properties->C\C++->Common Language Runtime Support- /clr)
The problem is:
Communicating between native\managed classes, since .H files cannot be set to use /clr, those cannot be used to reference a managed class elsewhere including other /clr files within the same project. (ie, you can create /clr files, but, they can't talk to each other, nor can you reference them within native portions of the project.)
The best solution I can find is to create a "glue" C# .dll file.
Create a new C# class library, add the Native DLL as a reference, then compile.
Now, in your native project, you can load the C# DLL, and access the natives /clr stuff through it. (The managed code you reference this way can be used with native\managed code.)
It's very possible, but, I cannot find a straightforward way to accomplish this.
That's what the topic is about, there seems to be no way to reference /clr classes due to header files not working when you set /clr at the file level. (ie, a header cannot contain /clr code unless the WHOLE project is set to /clr.)
There must be a way to reference /clr stuff without headers, or C++\CLI is just broken, I can easily load native code into /clr files by using pragma + headers, however, the reverse is looking impossible short of my "glue" solution.
That is what I believe this topic is about.
My method works, but, it's very tricky to get right, and compilation is a pain due to circular dependencies, etc,.
I really hope there is a proper way to do this, I've been looking, and my search led me here...
The real solution, would be to make .h files support /clr, then you could define your managed class in the header, and be able to freely reference it using standard methods, like include\using\pragma, etc,.
Perhaps you're looking for
#if __cplusplus_cli
Documented here on MSDN

I get LNK2028 when trying to wrap native c++ class using managed c++

trying to wrap a native cpp class using managed c++ class.
all looks good but for some reason it wont compile.
getting the following linker errors:
Error 25 error LNK2028: unresolved token (0A0002CE)
Error 27 error LNK2019: unresolved external symbol
Any ideas how do I fix this one ? :\
well, here is a full error of one of the functions:
Error 20 error LNK2028: unresolved token (0A0002CF) "public: bool __thiscall RCSclient::ResumeChannel(char *,int,__int64)" (?ResumeChannel#RCSclient##$$FQAE_NPADH_J#Z) referenced in function "public: bool __clrcall RCSClientWrapper::RCSclientWrapper::ResumeChannel(class System::String ^,int,class System::DateTime ^)" (?ResumeChannel#RCSclientWrapper#RCSClientWrapper##$$FQ$AAM_NP$AAVString#System##HP$AAVDateTime#4##Z) RCSClientWrapper.obj RCSClientWrapper
Tried to add the user32.lib with no results..
Ofer
C++/CLI allows you
to mix in native C++ pretty much at will, but using C++/CLI makes your app
depend on the .NET framework.
The reason is your C++/CLI project doesn't have some libs (user32.lib, in example) setup in the linker input is that the .NET framework already provides similar services, and the
IDE assumes that you prefer those to the older, native ones.
Check your project and add reference to the corresponding library.
Maybe you forgot an virtual keyword into the native C++ header function declaration
to call from managed wrapper!?