Errors using the glut library with C++/CLI - 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.

Related

How to define entry point in C++/CLI DLL with command line argument /ENTRY

There is an option in cl.exe to define custom entry point in a DLL with command line attribute /ENTRY. Unfortunately, it does not provide an example of how to use it.
http://msdn.microsoft.com/en-us/library/f9t8842e%28v=vs.100%29.aspx
I created managed C++ DLL with support of /CLR and replaced name of main function with "Start":
int Start(int argc, char *argv[])
{
return 0;
}
Then I try to compile this DLL from command line with this BAT command:
"c:\Program Files\Microsoft Visual Studio 12.0\VC\bin\cl.exe" ^
/clr /Fo /Z7 /D "NDEBUG" ^
/ENTRY:Start ^
"..\Links\Links.cpp"
Unfortunately, I get this error:
LNK1561: Entry point must be defined
Question: What exactly should I pass as /ENTRY argument?
Edit: as it was mentioned in Hans' comment below, function used to be an entry point in the DLL needs to have another signature so I corrected example above. Function presented below is an example of entry point for EXE file, particularly because it has managed type among its parameters.
int Start(array<String ^> ^ argc)
{
return 0;
}
Specifying /ENTRY on a managed assembly is a really bad idea, because now all the .NET Framework support code in the C++ runtime library won't be executed. Initializers of global C++ objects won't get a chance to run either. And you may get memory leaks on worker threads, because the C++ runtime library is smart enough to perform thread-local initialization when needed, but because it isn't receiving thread detach events, it won't be able to clean up. On the other hand, C++/CLI assemblies always dynamically link to the runtime DLLs, so at least that library DllMain will receive thread notifications, and resources used by the runtime itself won't be leaked.
Just leave the DllMainCRTStartup entrypoint provided by the library alone, and provide a function named DllMain which the library entry point will call.
There is plenty of documentation on MSDN concerning initialization code in C++/CLI managed assemblies:
Initialization of Mixed Assemblies
One of the important things to take away from that is that the DllMain signature (which again, is NOT the actual entrypoint, it is called from the library-provided entrypoint), is
BOOL WINAPI DllMain(
_In_ HINSTANCE hinstDLL,
_In_ DWORD fdwReason,
_In_ LPVOID lpvReserved
);
Silly me. Option /ENTRY is an argument for link.exe, not for cl.exe
With the following BAT script I can force my assembly to have custom entry point. The only thing is that in some reason in this case linker requires to set type of the project directly with /SUBSYSTEM option.
"c:\Program Files\Microsoft Visual Studio 12.0\VC\bin\link.exe" ^
/DLL /ENTRY:Start ^
/SUBSYSTEM:CONSOLE ^
/WX ^
/OUT:Links.dll ^
"Links.obj"

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

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.

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