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

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!?

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.

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.

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

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.

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

ICollectionPtr COM

I have an issue that ive been batteling with for a day or so now and im wondering if anyone might be able to help:
Im am trying to use the ActiveMQ-NMS to dequeue messages via COM in a C++ application. I have managed to build the source and override the 'ComVisible' flag in order to export all the types in the assembly via RegAsm (i did receive warnings about this and the 'Atomic' class but i dont think this is the issue i am facing at the moment).
As part of the RegAsm i have generated a .tlb file that i use in a #import in the C++ client. However, i then receive various errors whilst compiling. Things like:
error C2146: syntax error : missing ';' before identifier 'Keys'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
Essentially, it looks like things like the ICollectionPtr (and various others) are unavailable. Can anyone help me as to resolving these issues? Essentially im looking to register the .net ActiveMQ-NMS assembly as a COM compliant component and then use it from C++...
Unless there's some other reason to use COM and NMS, why not just use the ActiveMQ-CPP client? Then you can avoid all the complexity of COM. ActiveMQ-CPP is located here: