In my current project I have multiple ATL projects that depend on each other. One of them is called "Common" and defines a trace category, other projects might use to print out trace information.
I defined the category from the IDL file like so:
cpp_quote("static ATL::CTraceCategory DATA_LAYER(_T(\"Data Layer\"), 1);")
Basically this translates to the following definition inside the common header file, other projects include to get informed about the interfaces of the "Common" project.
static ATL::CTraceCategory DATA_LAYER(_T("Data Layer"), 1);
Now since Visual Studio 2013 there appears to be a change in how tracing works.
This does cause source-breaking changes in some uses of the ATL::CTraceCategory class, which will require changes in source code when migrating to Visual Studio 2013.
And indeed, I had to change the line above by removing the second parameter:
cpp_quote("static ATL::CTraceCategory DATA_LAYER(_T(\"Data Layer\"));")
Now everything builds again, but the problem raises as soon as I try to rebuild any project that uses the trace category. After the build successfully finished, the compiler automatically registers the component. And during regsvr32 /s "C:\...\Common.dll" I always receive an debug assertation like this:
Microsoft Visual C++ Runtime Library
Debug Assertion Failed!
Program: ...\x64\Debug\Common.dll
File: c:\program files (x86)\microsoft visual studio 14.0\vc\atlmfc\include\atltrace.h
Line: 337
Expression: false && "Too many categories defined"
This also happens when I try to register the component manually. Only projects that do not depend on the common project and therefor not use any trace category are registered successfully.
Does anybody have a solution for this? I would also accept a solution that shows another way of tracing in ATL, since there does not appear to be any difference to using DebugOutputString instead (If I understood the linked blog correctly).
Okay, I finally figured this out. The problem was related to the declaration of the trace category as static. I have no idea why this built in previous versions of Visual Studio. Anyway, here's the fix: First of all, I changed the definition of the trace category inside my Common.idl file:
cpp_quote("#ifdef DEFINE_EXPORTS")
cpp_quote("__declspec(dllexport) extern ATL::CTraceCategory DATA_LAYER;")
cpp_quote("#else // DEFINE_EXPORTS")
cpp_quote("__declspec(dllimport) ATL::CTraceCategory DATA_LAYER;")
cpp_quote("#endif // DEFINE_EXPORTS")
As you can see, the trace category now exports to the library, if DEFINE_EXPORTS is defined, which is true for the common project. All projects referencing this library are importing the definition (by including Common.h, which get's created from the idl file). If you define the trace category as static, each library defines a category on it's own. I think that was the cause for the error I was facing.
Now inside the dllmain.cpp file of the common project I define the trace categories:
#if (_MSC_VER >= 1800)
ATL::CTraceCategory DATA_LAYER(_T("Data Layer"));
#else
ATL::CTraceCategory DATA_LAYER(_T("Data Layer"), 1);
#endif
Note that the code switches between two constructors based on the VC++ version it is compiled with. It should be possible to get rid of this by using the CTraceCategoryEx template, but I stick to this method for now.
Finally all I had to do was adding the Common.lib reference to the Additional Dependencies of the projects referencing it.
Related
I've downloaded the latest copy from Latest Open EXR repo and compiled most everything without any problems. However, when I get to PyILMBase it fails.
There are two distinct issues with my attempts:
Error C2491 'PyImath::FixedArray::name': definition of dllimport function not allowed PyImath (...)\src\pyilmbase-2.2.1\PyImath\PyImath.cpp 41
and an import to unistd.h that kind of gets addressed Here
my question being, has anybody successfully compiled this for windows? It seems odd that I can't find any specific info about that compiling error. Am I missing something in the way that C++ works?
This project makes extensive use of whatever it is that causes the error C2491, so going in and changing it would be a little complicated
IlmBase is compiled as a shared library. A shared library must provide their function declarations in order your program can find them.
It's perform by declaring them as dllimport or dllexport depending on the situation.
__declspec(dllimport): imports the implementation from a DLL so your application can use it.
__declspec(dllexport): tells the linker that you want this object to be made available for other DLL's to import. It is used when creating a DLL that others can link to.
These keywords are generally handled by a single macro. In your case PYIMATH_EXPORT.
These lines are from PyImathTask.h
#if defined(PYIMATH_EXPORTS) // create library
#define PYIMATH_EXPORT __declspec(dllexport)
#else // use library
#define PYIMATH_EXPORT __declspec(dllimport)
#endif
So, because you want to make these functions available from your application, you must add PYIMATH_EXPORTS as a preprocessor definition.
Actually, PyIMath's properties mispells it - they've write it as PyImath_EXPORTS - ...
To fix that, in vs2015, go to the PyImath's properties > Configuration Properties > C/C++ > Preprocessor > Replace PyImath_EXPORTS by PYIMATH_EXPORTS.
It's probably the same thing for PyIex...
I am writing my own C++ project library in visual studio (couple of projects that consist of *cpp, *.h files, NOT an actual .lib file). Each of these projects is located in single Visual Studio "solution".
When I needed to use a code from one project in another, I just copied it. But that was short term solution. Now my library has grown both in size and functionality, and because of code duplication I ended up with dozens of different versions of the same file.
That single solution serve me as a playground // test ground for new ideas. I am developing projects not libs. Currently it holds about 50 projects.
I am working on visual studio 2015.
Lets say I have setup like this:
DataIO project located in */Solution/#DataInputAndOutput/DataIO/DataIO.h
consist both of DataIO.h and DataIO.cpp
Foo project located in */Solution/#Foo/Foo/Foo.h
consist both of Foo.h and Foo.cpp
DataIO.h:
#pragma once
#ifndef __DATA_IO_H__
#define __DATA_IO_H__
// ...
extern FILE * const logFile;
// Bunch of function declarations
#endif // !__DATA_IO_H__
I know that this is not a "Minimal, Complete, and Verifiable example" but my problem lies in logistic of things, not things themselves. And I believe that my description is sufficient.
Problem #1: In Foo.cpp I #include "DataIO.h" (with is possible because i added additional include directories in Foo project setup) But whenever I try to compile Foo I am given following error: unresolved external symbol for every function declaration inside DataIO.h and that one external variable. How Can I Fix this problem? Do I need to create a DataIO.lib to keep things straight?
I tried to add DataIO.h and DataIO.cpp into Foo project directly (NOT copy it, just add it into project) but that seems like a bad idea...
I recommend trying out the new "Shared Items Project" in VS2015+. A Shared Items Project is literally just a set of files. The project itself doesn't build anything. In fact, there are no (or almost no) compilation or linkage settings in a Shared Items Project -- those settings come the the project that references the Shared Items Project. When you reference a Shared Items Project from some other project FOO, the build of FOO happens as if the files of the Shared Items Project are items of the referencing project.
Short of that, you can set up your shared projects to build .libs and then use Project References within Visual Studio to automatically set up the linkage. I think you have to manually set up the include paths when doing this, though.
The best way to do this is to factor out common code into a library so the common code resides in one place. And then have your projects use the library - via an include file and linking with said library.
I am working on a project using c++/windows forms (visual studio 2010), we have 4 projects:
1 project containing GUI windows forms {managed code} and this is the exe project
other 3 projects {non-managed code} and all are static libraries.
in the 4 projects we don`t use precompilied headers stdafx.h , and common language runtime support is the Pure MSIL Common Language Runtime Support (/clr:pure).
every project include the other 3 projects as additional include directories , and link library dependencies set to yes.
We have:
Warning LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library
This warning appeared for the 3 static libraries projects in the same object files (.NETFramework,Version=v4.0.AssemblyAttributes.obj).
We want to eliminate it, but after some search, most topics speak about the precompiled headers to be a reason while we don not use it.
Any new ideas about why this warning exist and how to eliminate it?
Disclaimer: This solution is indeed terrible, and this code should not be added to production build! It is only useful to "hide" the warning.
A better solution would be to remove the file in question from the compilation, as it is anyway useless.
Original post:
I had a the problem with this warning originating from several dependencies, and I found that it was caused by some translation unit being empty, i.e. empty source files.
These files actually had a content but it was deactivated for visual studio so I just added at the beginning:
__declspec( dllexport ) void getRidOfLNK4221(){}
And now my project compiles without any warning :)
Hope it helps, even if this is a late answer!
I had a c++ static library with an empty module in it, linking which in non-optimized mode gave me that LNK4221 warning. (in Visual Studio)
I went to Librarian->All Options, and added "/ignore:4221" to Additional Options.
So, the warning has disappeared.
You get this warning because you use only template classes in cpp file.
To get rid of it, insert one simple function with no template.
See this:
https://learn.microsoft.com/en-us/cpp/error-messages/tool-errors/linker-tools-warning-lnk4221
In summary, the file exports nothing, so linker does not link, as it thinks it's a waste of effort
This was kind of just my particular problem but if your .cpp doesn't define any new functions or has empty bodies for constructor functions, you will get this warning. I used an initialization list for my constructor so the body was empty.
https://devblogs.microsoft.com/cppblog/linker-warning-lnk4221-and-some-tips-to-avoid-it/
In ” Visual Studio 2008 Command Prompt”, enter the following commands (Note: We use command line here to specify the order of .obj files; Visual Studio 2008 will supply linker with .obj files in alphabetical order)
cl /c a.cpp b.cpp
link /lib /out:test.lib a.obj b.obj
And LNK4221 will be thrown for a.obj as the following.
a.obj : warning LNK4221: no public symbols found; archive member will be inaccessible
For the above case, atlbase.h (shipped with Visual Studio) contains some definitions of symbols, which will be included in both a.obj and b.obj. Additionally, there is a function, func1, defined in b.obj. Linker will process OBJ files in Last In First Out manner, so when it is processing a.obj, it cannot find any new public symbols in it because b.obj provide all the public symbols that a.obj has, LNK4221 will be thrown. If command line 2 is replaced with following
link /lib /out:test.lib b.obj a.obj
Now the warning is gone!
I am getting this linker error.
mfcs80.lib(dllmodul.obj) : error LNK2005: _DllMain#12 already defined in MSVCRT.lib(dllmain.obj)
Please tell me the correct way of eliminating this bug. I read solution on microsoft support site about this bug but it didnt helped much.
I am using VS 2005 with Platform SDK
I had the same error message, but none of the answers here solved it for me.
So if you Encounter that Problem when creating a DLL Project that uses MFC, it can be resolved by entering the following line:
extern "C" { int _afxForceUSRDLL; }
to the cpp file where DllMain is defined. Then your own DllMain implementation is used, rather than the one from dllmain.obj.
When we try to use MFC library, we surely will include afx.h directly
or indirectly, then MFC(afx.h) tell the linker to find the symbol of
__afxForceUSRDLL and put that object which contains __afxForceUSRDLL into the program, so linker searches and puts dllmodule.obj into our
program, because __afxForceUSRDLL is defined in dllmodule.cpp.
That’s the common scenario. When we want to use our own DllMain in a
mfc dll project, linker complains that there are two DllMain, one in
our code, one in Dllmodule.obj.
So we need to tell the linker to add our dllmain.obj for
__afxForceUSRDLL. So we need to define __afxForceUSRDLL in our own cpp file where our own DllMain is defined, then the linker will ignore
mfc’s dllmodule.obj and see only one DllMain and never complains.
Source: http://social.msdn.microsoft.com/Forums/en-US/0d78aa6b-1e87-4c01-a4a7-691335b7351a/how-to-build-mfc-application-dll-in-visual-c-2010
If you read the linker error thoroughly, and apply some knowledge, you may get there yourself:
The linker links a number of compiled objects and libraries together to get a binary.
Each object/library describes
what symbols it expects to be present in other objects
what symbols it defines
If two objects define the same symbol, you get exactly this linker error. In your case, both mfcs80.lib and MSVCRT.lib define the _DllMain#12 symbol.
Getting rid of the error:
find out which of both libraries you actually need
find out how to tell the linker not to use the other one (using e.g. the tip from James Hopkin)
If you're defining your own DllMain, in your project settings you need to set 'Use of MFC' in the 'Configuration Properties/General' to 'Use Standard Windows Libraries'.
You should do a clean rebuild after changing it.
In my project I was able to solve this problem by adding mfcs80.lib and msvcrt.lib as additional dependencies in the project settings. The 'additional dependencies' can be found under Linker -> Input.
In the debug configuration that would have to be mfcs80d.lib and msvcrtd.lib respectively.
By the way, I am working with Visual Studio 2010, so in my case the MFC lib is called mfc100.lib.
I am not sure why this worked. It is not necessary to add these lib files as additional dependencies because I already set 'Use of MFC' to 'Use MFC in a shared dll'. I guess that by specifying these libraries as additional dependencies they are linked in a different order.
This solution is more or less the same as the one suggested on the Microsoft site: http://support.microsoft.com/kb/148652, except I did not need to type anything in the 'Ignore specific default libraries' box.
For me the direct cause was indeed a missing _afxForceUSRDLL symbol reference, but the indirect cause was a missing _USRDLL macro definition. It is defined by default by the VC wizard, but occasionally devs erase it erroneously.
Here it is in more words.
MSDN knowledge base ID Q148652.
http://support.microsoft.com/kb/148652
Cause:
Visual C++ compiles the source files in alphabetical order, and passes the compiled object files to the linker in alphabetical order.
If the linker processes DLLDATAX.OBJ first, the source code references DllMain, which the linker loads from MSVCRTD.LIB(dllmain.obj).
The linker then processes an object file compiled from a C++ file that contains #include "stdafx.h", which references the symbol
__afxForceUSRDLL, which the linker loads from MFC42D.LIB(dllmodul.obj). This object module also contains an implementation for DllMain,
causing the conflict.
I have a very similar problem. [mfcs110d.lib(dllmodul.obj) : error LNK2005: _DllMain#12 already defined in MSVCRTD.lib(dllmain.obj)] and the solution was add mfcs110d.lib to Additional Dependencies
For all those who are experiencing this error in ATL projects (mostly when trying to add MFC support), here's the solution I found after days of frustration!
First of all, this link was more helpful to me than all the others. It pointed me into the right direction. The problem occurs, if the "generated files" (containing the proxy and stub code, just as the type guids) for some reason have been removed and readded to the project. This causes Visual Studio to add them in the wrong order!
Usually you first come up with the "ATL requires C++ compilation" error, but you may have fixed this by turning out the Yc/Yu (precompiled headers) setting for that file.
What you should do next is unloading your project and edit it. Search for the item groups that define the build and include order (ClCompile and ClInclude). Check their order and settings.
The compiles should appear in this order:
dllmain.cpp (with CompileAsManaged set to false and PrecompiledHeader left empty).
Library source (MyLib.cpp, containing DllCanUnloadNow and so on)
Proxy/Stub code (MyLib_i.c; with same settings as dllmain.cpp)
stdafx.cpp (with PrecompiledHeader set to Create)
All the other library source files (your actual libraries content)
xdlldata.c (with the same settings as dllmain.cpp)
The includes should then be ordered like this:
dllmain.h
MyLib_i.h
Resource.h
stdafx.h
targetver.h
... (actual library headers)
xdlldata.h
Fixing the build order fixed my project and I was able to create a new clean build.
I have personally got rid of this error this way: right-clicked project in the Solution Explorer, selected Properties from pop-up menu, clicked Linker tab and added mfcs71ud.lib into Additional Dependencies. If you're using Visual Studio 2005, it should be "80" instead of "71" and so on.
In my case I had a problem with the preprocessor directives.
For some reason _USRDLL was defined, when it should not have been.
To check this, go to the menu Project , select Project Properties , then select the snippet Configuration Properties --> Preprocessor .
The preprocessor directives will be found there.
Declare the mfc80ud.lib and mfcs80ud.lib in the Additional Dependancies field in the Project Properties -> Linker Tab -> Input of Visual Studio to fix the issue.
Just #undef the _USRDLL before including afx.h, or even better, edit your project configuration and remove the macro.
This is the usual configuration for a MFC extension DLL: Build Settings for an MFC DLL
Make sure you include "Stdafx.h" at the top of each .cpp file. I was getting the exact same error and had a single .cpp file that did not include this header at all. Adding the #include solved the problem.
I found solution Here
Visual Studio 2010 library linking order
this is: /FORCE:MULTIPLE
in linker options
I had to mix ATL and MFC together , to use
[module(name = "mymodule")]; construction in MFC application together with "__hook" keyword
I found this which helped me:
http://support.microsoft.com/kb/148652
Basically the linker order was incorrect. the CRT libs were getting linked before the MFC libs. Turns out, the MFC libs had to get linked FIRST, and then the CRT libs could be linked.
Yucko Microsoft!!
There is a common theme running through some of the answers here.
Avishek Bose:-
Declare the mfc80ud.lib and mfcs80ud.lib in the Additional
Dependancies field in the Project Properties -> Linker Tab -> Input of
Visual Studio to fix the issue.
vmb100:-
I am working with Visual Studio 2010, so in my case the MFC lib is
called mfc100.lib.
joseAndresGomezTovar:-
I have a very similar problem. [mfcs110d.lib(dllmodul.obj) : error
LNK2005: _DllMain#12 already defined in MSVCRTD.lib(dllmain.obj)] and
the solution was add mfcs110d.lib to Additional Dependencies
So the general case seems to be to first find the name of the library to add ...
and then to add it ....
Note that there seem to be some prerequisites and/or alternative solutions.
This can also occur if your solution has multiple projects that export the same symbols. For example if you have sub-project that builds foo.dll with a foo.def file that exports DoFoo and a sub-project for bar.dll with a bar.def file that exports DoFoo, a collision will occur and this is the error you will see when you link.
Does anyone know how to get IntelliSense to work reliably when working in C/C++ projects? It seems to work for about 1 in 10 files. Visual Studio 2005 seems to be a lot better than 2008.
Edit: Whilst not necessarily a solution, the work-around provided here:
How to get IntelliSense to reliably work in Visual Studio 2008
Is probably the best bet if I want a decent IntelliSense system.
Native C++ intellisense does not work reliably in any version of Visual Studio. I find there are two common problems:
1) Header file paths are not set-up correctly. When you find a type where intellisense is not working, use the IDE to click through each header file to find the one containing the type. (Right click on #include and select Open Document...). If this fails before you get to the file which declares the type then this is your problem. Make sure header file search paths are set-up correctly.
And,
2) The intellisense database is corrupt. This happens ALL The time. You need to close the solution, delete the .ncb file, and then reopen the solution. I posted the macro I use for this in answer to another question here.
The preprocessor can also confuse intellisense - so make sure any #defines during build are also available to intellisense. Other than that, I don't know what else can break it. I've not seen any particular issues with forward declarations.
I've also realized than Intellisense is sometime 'lost', on some big project. Why? No idea.
This is why we have bought Visual Assist (from Tomato software) and disabled Intellisense by deleting the dll feacp.dll in the Visual studio subdirectory (C:\Program Files\Microsoft Visual Studio 8\VC\vcpackages)
This is not a solution, just a workaround.
It looks like there's hope on the horizon for those of us unable to obtain Visual Assist:
Rebuilding Intellisense
Do you have any add-ins installed (or uninstalled)? I find that effects my intellisense.
Besides that just making sure your Tools->Options->Text Editor->All Languages "Auto List Members" and "Parameter Information" are checked off.
I don't use VS2008 for C++, only VB & C#, but I find that when intellisense stops working (true for VS2003/2005/2008) it's because something in the project/file is broken - usually a bad reference or code.
VB and C# have much better intellisense support due to the ability to reflect on the referenced assemblies to build the intellisense tree.
C++ has to walk the include files for function prototypes, and if the paths are not correct it will not find all the prototype headers.
My fix to itellisense was required after that awful refactor utility minced my code. The problem was a class header file that included an #include of itself. The recursive reference destroys itellisense. A symptom of this is if itellisense can see other classes but not the current one. Also:
Use #pragma once to eliminate duplicate header loads
If the project now takes a very much longer time to load, that itellisense trying to make sense of the conflict that is causing then lack of completion support.
Often it is only one class object that is affected, This shows you what files (usually headers) to look at.
#John Richardson / #Jonathan Holland
My includes are setup correctly, no problems there. I've also tried the NCB rebuild several times but it never fixes it 100%.
I have a feeling it may be to do with forward declarations of classes. e.g. to reduce the complexity of includes in header files we normally do something like:
class MyPredeclared;
class SomeOtherClass
{
private:
MyPredeclared* m_pPointer;
}
I wonder if that screws it up? Any other ideas? It definitely gets worse the larger your project gets.
I had a very annoying problem, intellisense was working only in some files, without any evident reason... it took me a couple of hours of digging through google, but I finally understood that the reason was indeed recursive reference!
I was using the:
#ifndef CLASS_H
#define CLASS_H
...
#endif
to avoid redefinition of symbols, and this sometimes breaks intellisense in big projects.
But it is enough to comment the ifndef-define-endif and put a:
#pragma once
at the beginning of the header files to still avoid redefinitions and have Intellisense working again =)=)
At least, this worked for me, hope it's useful...
Cheers
Francesco
I have recently studied Intellisense in VS2008, as I'm developing a rather large C++ numerical linear algebra library where templates and such are used extensively. Intellisense stopped working shortly into the project and I sort of gave up, but now it became really annoying without it so I set to investigate. This is what I found out:
Assuming there is a file(s), containing code that "breaks" Intellisense,
if header files that break Intellisense are in the project, but are not #included, it still works in the rest of the files
if they are included, but no type declared inside is used, it still works
if they are included and a type declared inside is used, it might still work a bit (no Intellisense for members, no Intellisense after occurrence of given type, but at least global names and argument info before)
if Intellisense is broken in one .cpp file, it can still work in the others where the problematic code is not included or used (but i imagine if it crashes bad, it will get disabled for the whole project, although that did not happen to me)
Intellisense seems to be updated after successful compilation (sometimes not before)
putting broken code inside any of #if 0, /* .. */ or // seems to put Intellisense at ease
From the C++ features I used, actually only a few break Intellisense:
comparison with '>' or '>=' in template parameter (e.g. static_assert<(size > 0)>)
not solved by using double parentheses (static_assert<((size > 0))> does not help)
solved by using '<' or '<=' instead (static_assert<0 < size> works)
solved by storing the value in enum and using that to specialize the template
explicit function template specialization disables argument info (e.g. function<type>(args))
probably unable to solve (maybe wrap in a macro), but I can live with it being broken
instantiation of template member type, such as Matrix::MakeMatrixType<3, 3>::Result r;
kind of hard to figure out exactly why this happens (likely because of use of Eigen)
workaround by moving such code in a separate .cpp where IS won't work (not always possible)
It would seem that some of those problems are due to some "simplified" parsing, which is less strong than a proper C++ parser. With the above information at hand, a "reliable" method of making Intellisense work in an existing code:
Set up an empty project (a console app), create Main.cpp with dummy void main() {} in it.
Include one of your broken header files, and math.h
Build (it must compile, in order for Intellisense to update reliably)
Test whether Intellisense is working by typing e.g. sin( and seeing if argument help pops up. Sometimes, this would work, but member help wouldn't - so try that as well.
Make an instance of something in the header file, build, see if that manages to kill IS.
Remove code from the culprit file and go to step 3
After finding and fixing problematic code, put back code removed in step 5, try again
After making a whole class work well, make an instance of the next class, and so on ...
I found it easy this way to pinpoint locations of code that made problems (I realize that this might be unfeasible for really large projects, in my case only a single file out of 97 made problems). Note that 'Build' here refers to compiling, the linking stage does not need to finish, so unresolved externals are ok, the IS should update regardless.
Another method of updating IS (other than building) is to save everything, close workspace, delete .ncb file and reopen it. Then wait for 'Updating Intellisense ... (N)' to disappear from the status bar (N counts towards zero, if it doesn't go all the way, it kind of shows progress where problems occurred). I found this rather tedious.
About this problem i've notice something interesting (on Visual Studio 2010):
to solve this problem i've changed #include sintax in my header files, before was (old project done with VS 2005 and reopened using VS 2010):
#include <myfile.h>
and i fix this with:
#include "myfile.h"
After intellisense start working correctly!
I hope this can help!
I had to reset the settings...
C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE>devenv.exe /ResetSettings
thread on this here
The problem is with the .vcproj files.
You will find if you switch to release mode from debug mode, build, then try intellisense it often works.
Close Visual Studio. If you search for the .vcproj files in your project, edit them and search for the first two instances of AdditionalIncludeDirectories. The value for this should look something like "..\,....\" rather than "../..".
Reopen your project, let the Intellisense finish building, then it should be fixed.