I got the following declaration:
// file MadaPacket.h
class MadaPacket
{
// ....
public:
inline static bool word_is_header(int w);
}
And as the correspondent declaration:
// file MadaPacket.cpp
#include "MadaPacket.h"
inline bool MadaPacket::word_is_header(int w)
{
return w == 0xFBBA;
}
MSVC12 builder fails at linkage, with the following reason:
unresolved external symbol "public: static bool __cdecl MadaPacket::word_is_header(int)
Adding static to definition pushes error
'static' should not be used on member functions defined at file scope
Removing inline from definition pushes error
unresolved external symbol "public: static bool __cdecl MadaPacket::word_is_header(int)
I guess I'm misunderstanding some of the definition-declaration relationship.
EDIT
Obviously I'd like to have both the modifiers, if this is possible ofc.
Remove the inline keyword from both places.
The inline keyword should be used only when defining functions in header files that are included from multiple translation units. Well, there are other situations where it can be used too, but here none of them apply.
You don't have an identical list of modifiers for your definition in your .h file and your .cpp file. Both definitions should be exactly the same for the linker to find them. So I'd first remove 'static' from both and recompile.
Related
I have a sample.c file where a non-static function is defined
Source: sample.c
#if defined(__cplusplus)
extern "C" {
#endif
int get_sample_value()
{
return 1000;
}
#if defined(__cplusplus)
}
#endif
There is pure C++ SDK project, sample_sdk which basically generates a couple of static-libs, where get_sample_value() function is used within one of the source files as follows:
Source: sample_sdk_source.cpp
extern int get_sample_value();
static void do_processing()
{
int sample_value = get_sample_value();
process( sample_value );
}
Above-mentioned sample.c will be compiled in another C++/CLI GUI application, SampleViewer where sample_sdk libs are included within this application.
But when compiling the SampleViewer we are getting the following error:
libsample-sdk-x86.lib(sample_sdk_source.obj) : error LNK2019:
unresolved external symbol "int __cdecl get_sample_value()"
(?get_sample_value##YAPBUint##XZ) referenced in function "public:
static void __cdecl do_processing()" (?do_processing##SAXXZ)
I also tried to use the same function from SampleViewer::main.cpp file, but the same error exists.
Is there any issue when accessing function defined in C file as extern from C++/CLI environment?
The linker error says it all:
Your extern int get_sample_value(); declaration in C++ sets up an undefined symbol for the mangled name ?get_sample_value##YAPBUint##XZ
Your definition in sample.c defines a symbol with a non-mangled name (_get_sample_value).
To solve this, either mark your declaration in C++ with extern "C" as well, or better yet: move the declaration into a header that both sample.c and sample_sdk_source.cpp can include (with the #if defined(__cplusplus) guard)
using Visual C++ 2008, I am having an "Unresolved external symbol" even if with the IDE I can correctly see both declaration and definition of the function:
The error:
hook_file.obj : error LNK2001: unresolved external symbol "int __cdecl is_directory_objattr(struct _OBJECT_ATTRIBUTES const *)" (?is_directory_objattr##YAHPBU_OBJECT_ATTRIBUTES###Z)
Relevant code in hook_file.cpp:
#include "misc.h"
void handle_new_file(HANDLE file_handle, const OBJECT_ATTRIBUTES *obj)
{
if(is_directory_objattr(obj) == 0 ) {
// etc.
Declaration in misc.h file:
BOOL is_directory_objattr(const OBJECT_ATTRIBUTES *obj);
Definition in misc.cpp file:
#include "misc.h"
BOOL is_directory_objattr(const OBJECT_ATTRIBUTES *obj)
{ //function body here }
I really don't get what the linker has to complain here.
The header with function declaration is included by the file which
calls the function.
The cpp file with the function definition included header file with declaration.
Declaration and definitions are identical.
All files are listed among project files.
Any idea whats wrong?
Thanks!
Have you only include one time your header file?
in misc.h
#ifndef MISC
#define MISC
...
#endif MISC ?
I have an MFC application AVT_testapp, and in the header file (AVT_testappDlg.h) I am trying to create a variable outside of all functions, classes, etc. in order to make it global. Whenever I try to do this though (say I try int x = 7), I get the error:
1>AVT_testappDlg.obj : error LNK2005: "int x" (?x##3HA) already defined in
AVT_testapp.obj
1>..\..\bin\x64\Debug\AVT_testapp.exe : fatal error LNK1169: one or more
multiply defined symbols found
Everything I have found on google says "just add header guards". AVT_testappDlg has 6 #include's, and each of them has header guards.
What else could be causing these errors when creating global variables?
EDIT: Here is the beginning of my header file,
#pragma once
#include "../../src/CoreUtils/nierr.h"
#include "..\..\src\CoreUtils\StringHelpers.h" //includes windows.h
#include "afxwin.h"
#include "afxcmn.h"
#include "IFrameObserver.h"
#include "c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\GdiPlusHeaders.h"
//#include <fstream>
//#include <windows.h>
int x = 7;
using namespace AVT::VmbAPI;
//////////////////////////////////////////////////////////////////////////
////////// MyObserver class ///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
class MyObserver : public IFrameObserver
{
private:
MyObserver( MyObserver& );
MyObserver& operator=( const MyObserver& );
public:
VmbUchar_t* imageData;
//...
//...
//...
//...
//that's the end of the relevant stuff
You cannot define variables at namespace level in a header. In general it is best not to have global variables, but if you need to you should provide only a declaration in the header and the definition in a single .cpp:
//header
extern int i;
//cpp
int i;
The problem with your code is not related to header guards. Header guards ensure that a header is parsed only once in each translation unit. Lack of header guards causes compiler errors, where the compiler sees, say for example a class, defined multiple times in the same translation unit after preprocessing. In your case the error is a linker error LNK2005, and it means that the same symbol was defined in multiple translation units (in your case in each translation unit that includes the header with the definition).
If the global variable is not const(*), you cannot put it in a header file and include it in multiple translation units (i.e. .cpp files). Otherwise, you will end up with multiple definitions of the same symbol in your program, violating the ODR (One Definition Rule, see Paragraph 3.2 of the C++11 Standard), and the linker will complain about that.
You should use the extern modifier in your shared header to provide only a declaration of your variable:
extern int var;
Then, in one single .cpp file, you can provide a definition for it:
int var;
(*) const global variables have internal linkage by default, so each translation unit will end up having a private copy of it and no multiple definition will occur.
if you insist on having a global variable at least put it in a namespace to avoid collisions with other modules
namespace globals
{
extern int x;
}
then in the .cpp file define it.
int globals::x = 0;
it also makes it more clear that it is a global variable.
MyNamespace.h:
namespace MyNamespace{
int a
}
MyNamespace.cpp: some function that uses a
main.cpp
#include "MyNamespace.h"
main.obj : error LNK2005: "class std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class std::allocator<wchar_t> >
FileNamespace::m_rootDirectoryPath"
(?m_rootDirectoryPath#FileNamespace##3V?$basic_string#_WU?$char_traits#_W#std##V?$allocator#_W#2##std##A)
already defined in FileNamespace.obj
1>main.obj : error LNK2005: "struct FileNamespace::FileTree FileNamespace::m_dataFileTree"
(?m_dataFileTree#FileNamespace##3UFileTree#1#A) already defined in
FileNamespace.obj
You are defining a global variable (with external linkage) in multiple translation units, which results in duplicate definition errors (since you are violating the ODR).
What you should do, instead, is to declare it in the header with an extern declaration
namespace MyNamespace{
extern int a;
}
and define it in a single .cpp file (probably in MyNamespace.cpp)
int MyNamespace::a;
This way, the compiler will create only one instance of this variable in a single object module, and the linker will link all the references to it made in other object modules to this single instance.
It may help you to understand the problem noticing that this is the exact equivalent of declaring functions in headers (writing there only the prototype) and defining them in a single .cpp.
Namespaces are no different from other variables; in your header, you are actually defining the "a", not just declaring it.
In your header:
namespace MyNamespace{
extern int a;
}
In one source file:
int MyNamespace::a;
This is something that makes me fairly perplexed.
I have a C++ file that implements a set of functions, and a header file that defines prototypes for them.
When building with Visual Studio or MingW-gcc, I get linking errors on two of the functions, and adding an 'extern "C"' qualifier resolved the error. How is this possible?
Header file, "some_header.h":
// Definition of struct DEMO_GLOBAL_DATA omitted
DWORD WINAPI ThreadFunction(LPVOID lpData);
void WriteLogString(void *pUserData, const char *pString, unsigned long nStringLen);
void CheckValid(DEMO_GLOBAL_DATA *pData);
int HandleStart(DEMO_GLOBAL_DATA * pDAta, TCHAR * pLogFileName);
void HandleEnd(DEMO_GLOBAL_DATA *pData);
C++ file, "some_implementation.cpp"
#include "some_header.h"
DWORD WINAPI ThreadFunction(LPVOID lpData) { /* omitted */ }
void WriteLogString(void *pUserData, const char *pString, unsigned long nStringLen) { /* omitted */ }
void CheckValid(DEMO_GLOBAL_DATA *pData) { /* omitted */ }
int HandleStart(DEMO_GLOBAL_DATA * pDAta, TCHAR * pLogFileName) { /* omitted */ }
void HandleEnd(DEMO_GLOBAL_DATA *pData) { /* omitted */ }
The implementations compile without warnings, but when linking with the UI code that calls these, I get a normal
error LNK2001: unresolved external symbol "int __cdecl HandleStart(struct _DEMO_GLOBAL_DATA *, wchar_t *)
error LNK2001: unresolved external symbol "void __cdecl CheckValid(struct _DEMO_MAIN_GLOBAL_DATA *
What really confuses me, now, is that only these two functions (HandleStart and CheckValid) seems to be built with C linkage. Explicitly adding "extern 'C'" declarations for only these two resolved the linking error, and the application builds and runs.
Adding "extern 'C'" on some other function, such as HandleEnd, introduces a new linking error, so that one is obviously compiled correctly.
The implementation file is never modified in any of this, only the prototypes.
The error indicates that nothing is wrong with your implementation file or header (as used by the implementation file) - the link error strongly suggests that the functions actually generated were generated with c++ linkage - Its the UI file thats incorrectly looking for the C-Linkage versions of the functions. Patching the definitions in the header is patching your implementation to conform to the probably incorrect demands of the UI, rather than the other way around.
Your UI file is either a .m or .c file, OR , if your UI file is a .cpp file you have dome something like:
// ui.cpp
extern "C" {
#include "some_header.h"
}
Of course, if your UI file is a .c file - you either need to change it to cpp, OR explicitly define the functions with C-linkage so they can be called from C.
Could the function names conflict with names declared in a header?
Do you get the same problem if you give the functions different names?