I'm using VS2008 WinCE7. I'm facing linking error during build.
The file system structure is
menu.c - ./menu.c
eboot.h - ./eboot.h
file_1.cpp - ./dir1/file_1.cpp
where . represents current directory
menu.c
#include <eboot.h>
static VOID OALWriteToEMMC(OAL_BLMENU_ITEM *pMenu);
VOID OALWriteToEMMC(OAL_BLMENU_ITEM *pMenu)
{
OALTestEMMC();
}
file_1.cpp
#include <eboot.h>
VOID OALTestEMMC();
VOID OALTestEMMC()
{
//some code
}
eboot.h
VOID OALTestEMMC();
I'm getting the error
menu.obj : error LNK2019: unresolved external symbol OALTestEMMC referenced in function OALWriteToEMMC
Please guide me how to solve it.
EDIT1:
menu.c
#ifdef __cplusplus
extern "C" VOID OALTestEMMC();
#endif
and removed the declaration in eboot.h and added it in file_1.cpp
But, the error persists.
It seems that you are compiling the function definition in C++ but the use of that function in C. Without making the function extern "C" in C++, the compiler will mangle the name, and generate a symbol that won't match the declaration used in the C code.
If you want to mix C and C++, make sure that the declarations in C++ are marked extern "C" so that the compiler won't mangle the names and will use the C calling conventions. Alternatively, compile everything in C++ (or in C)
David RodrÃguez's original answer is correct. You are invoking a C++ function (OALTestEMMC) from a C source file. As David mentioned, the C++ compiler will mangle the function name. In order to suppress the name mangling so that the code in menu.c can invoke it, place the 'extern "C"' qualifier on the OALTestEMMC function (in file_1.cpp):
extern "C" VOID OALTestEMMC();
extern "C" VOID OALTestEMMC() {
// stuff
}
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)
I have created an MSVS2015 project (MFC/C++) which
links with a static C library. When I build the
projects I get the following error:
error LNK2019:
unresolved external symbol "void __cdecl testLinkerError(void)" (?testLinkerError##YAXXZ) referenced
in function "void __cdecl test1(void)" (?test1##YAXXZ) [PATH_REMOVED]\test.obj [NAME_OF_MFC_PROJECT]
For debugging purposes, I have created 3 files:
test.cpp
linkertest.c
linkertest.h
test.cpp has been added to the MFC project and it looks like this:
#include "linkertest.h"
void test1(void)
{
testLinkerError();
}
The header file linkertest.h looks like this:
#pragma once
#ifdef _cplusplus
extern "C" {
#endif
void testLinkerError(void);
#ifdef _cplusplus
}
#endif
And linkertest.c looks like this:
#include "linkertest.h"
void testLinkerError(void) {
int x = 5;
int y = 7;
int z = x + y;
}
I am quite sure that this is some kind of name mangling issue, but I can't figure out how to solve it.
The calling convention in both projects is set to __cdecl
based on the compiler error, you compiler tried to look up ?testLinkerError##YAXXZ which is a C++ function name. so which means on your import part (not your DLL export) you did not use extern "C"....
and one more thing, The name __cplusplus (two underscores) is defined to the value 201402L when compiling a C++ translation unit. please check your code make sure _cplusplus (one underscore) is defined.
I'm trying to write a program that can manage the harddisks/volumes/partitions in a Windows system. It seemed like a good idea to use Windows' Virtual Disk Service to accomplish this.
I wrote a bit of code to try it out, but when linking it I get the following error: error LNK2001: unresolved external symbol _CLSID_VdsLoader
Microsofts sample code indicates that I have to link to ole32.lib, and from googling I learned that uuid.lib is also involved. The "Additional Dependencies" line in my project settings is the following:
kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
As you can see, both previously mentioned libraries are included.
I'm trying all this on Visual C++ Express for Windows Desktop 2013. Could this be the problem? Perhaps the express version does not support 100% of the available COM objects? If that's not it, what else could it be?
This is explained here: How to avoid error "LNK2001 unresolved external" by using DEFINE_GUID, you just need for example to add #include <InitGuid.h> in your stdafx.h file.
I had similar issue with unresolved external guid. I didn't define _MIDL_USE_GUIDDEF_ macro and tried to compile code as C++ code.
Since MIDL compiler generates C source file to define guids it is compiled as C code until you explicitly tell visual studio to compile code as C++ code.
MIDL-generated header file contains (when compiled as C++):
extern "C"
{
extern "C" const IID iid; // extern "C" is redundant, extern would be enough
}
MIDL-generated guids-definition file contains (when compiled as C++):
extern "C"
{
const IID iid = { ... }; // _MIDL_USE_GUIDDEF_ macro is not defined
}
We need to remember:
extern "C" block implies C name decoration; e.g.
extern "C" { int a; }
extern "C" singleton implies C name decoration AND extern semantics; e.g.
extern "C" int a;
in C++ non-extern namespace-scope const object implies internal linkage; e.g.
const int a; // internal linkage
extern const int b; // external linkage
With this in mind we can see that header file declares const IID iid with external linkage and C name decoration, whereas guids-definition file defines const IID iid with internal linkage and C name decoration. Linkages do not match, therefore they are treated as different entities by linker. In this case const IID iid with external linkage is left undefined and is later used in the same translation unit.
When you add predefined _MIDL_USE_GUIDDEF_ macro guids-definition file will contain:
extern "C"
{
extern "C" const IID iid = { ... }; // extern "C" is redundant, extern would be enough
}
So you need to add predefined _MIDL_USE_GUIDDEF_ macro in order to explicitly compile code as C++.
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?
I have a 3rd party library that's written in C. It exports all of its functions to a DLL.
I have the .h file, and I'm trying to load the DLL from my C++ program.
The first thing I tried was surrounding the parts where I #include the 3rd party lib in
#ifdef __cplusplus
extern "C" {
#endif
and, at the end
#ifdef __cplusplus
} // extern "C"
#endif
But the problem there was, all of the DLL file function linkage looked like this in their header files:
a_function = (void *)GetProcAddress(dll, "a_function");
While really a_function had type int (*a_function) (int *). Apparently MSVC++ compiler doesn't like this, while MSVC compiler does not seem to mind.
So I went through (brutal torture) and fixed them all to the pattern
typedef int (*_x_a_function) (int *); // using _a_function will not work, C uses it!
_x_a_function a_function ;
Then, to link it to the DLL code, in main():
a_function = (_x_a_function)GetProcAddress(dll, "a_function");
This SEEMS to make the compiler MUCH, MUCH happier, but it STILL complains with this final set of 143 errors, each saying for each of the DLL link attempts:
error LNK2005: _x_a_function already defined in main.obj main.obj
Multiple symbol definition errors.. sounds like a job for extern! SO I went and made ALL the function pointer declarations as follows:
function_pointers.h
typedef int (*_x_a_function) (int *);
extern _x_a_function a_function ;
And in a cpp file:
function_pointers.cpp
#include "function_pointers.h"
_x_a_function a_function ;
ALL fine and dandy.. except for linker errors now of the form:
error LNK2001: unresolved external symbol _a_function main.obj
Main.cpp includes "function_pointers.h", so it should know where to find each of the functions..
I am bamboozled. Does any one have any pointers to get me functional? (Pardon the pun..)
Linker errors like that suggest you've defined all the functions in function_pointers.cpp, but forgotten to add it to the project/makefile.
Either that, or you've forgotten to "extern C" the functions in function_pointers.cpp too.
I believe that if you declared the typedefs and/or the prototype as extern "C", you must remember to extern "C" the definition too.
When you link C functions the prototypes will get a leading _ in front of them by default so
when you do a typedef using the same name
typedef int (*_a_function) (int *);
_a_function a_function
you'll get issues because there is already a function in the dll named _a_function.
Usually you declare a function in yourlibrary.h like extern "C" __declspec(dllexport) int __cdecl factorial(int); then create that function in yourlibrary.c:
extern "C" __declspec(dllexport) int __cdecl factorial(int x) {
if(x == 0)
return 1;
else
return x * factorial(x - 1);
}
After compiling your DLL you get your .dll and .lib files. The latter is used when you want to import your functions to the project. You put #include "yourlibrary.h" and #pragma comment(lib, "yourlibrary.lib") in your project, after this you can use int factorial(int) in you application.