LNK2019: Calling C function from CPP code - c++

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.

Related

C++ dll and name mangling issue

I am trying out a simple test DLL project. Under my solution, I have two projects - first C++ Dll (library) and second C++ exe (driver). Below I've attached a snapshot of the basic project setup:
dllmain.h
#ifndef DLLMAIN_H_
#define DLLMAIN_H_
#ifdef FFMPEGLIB_EXPORTS
#define FFMPEGLIB_API __declspec(dllexport)
#else
#define FFMPEGLIB_API __declspec(dllimport)
#endif // FFMPEGLIB_EXPORTS
static void TestFoo();
extern "C" FFMPEGLIB_API void Test(int* num);
extern "C" FFMPEGLIB_API void ProxyFoo();
#endif
dllmain.cpp
#include "dllmain.h"
#include "A.h"
void TestFoo()
{
A a;
a.foo();
}
void Test(int* num)
{
*num = *num + 1;
}
void ProxyFoo()
{
TestFoo();
}
driver.cpp
#include <iostream>
#include "dllmain.h"
int main(int argc, char** argv)
{
int mum = 4;
Test(&num);
std::cout << num;
ProxyFoo();
return 0;
}
The library project compiles normally, but the exe fails to compile with a linker error:
Code Description Project File
LNK2001 unresolved extern symbol _imp_ProxyFoo driver driver.obj
LNK2001 unresolved extern symbol _imp_Test driver driver.obj
LNK1120 2 unresolved externals driver driver.exe
I have two questions here:
Why does the function name of dllmain.h get mangled in spite of being marked as extern "C"?
Why can I not create an instance of test class A from extern methods? What would be a good way of doing that?
Why the function name of dllmain.h getting mangled in spite being
marked as extern "C"?
Because __declspec(dllimport).
Why can I not create instance of test class A from extern methods?
What would be good way of doing it?
I think that's fine, but you didn't provide any class A code. Just do this:
class __declspec(dllexport) A
{
/* ... */
};
Why EXE compile failed?
This is because you have not imported the LIB file of the DLL into the project.
There are two ways to import it:
Add #program comment(lib, "<YOUR_LIB_FILE>.lib") to the code file.
Add <YOUR_LIB_FILE>.lib to Properties -> Linker -> Input -> Additional Dependencies.
Microsoft documentation: https://learn.microsoft.com/en-us/cpp/build/importing-and-exporting
You need to put the extern "C" thing around your function definitions that you intend to export in dllmain.cpp so it matches the linkage of your declaration.
Also, you need to do the declexport thing too.
extern "C"
{
__declspec(dllexport) void Test(int* num)
{
*num = *num + 1;
}
__declspec(dllexport) void ProxyFoo()
{
TestFoo();
}
}

LNK2019: Unresolved external symbol in C++/CLI

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)

LNK2019 unresolved external appears when function is used inside static method

I have a C++ Visual Studio 2013 console application which is supposed to make use of a DLL MyDLLlib.dll which I have written. MyDLLlib is written in C. One of the functions is called Get_Version. The prototype is
const char *Get_Version();
I put this at the top of the source files to make use of the prototype:
extern "C"{
#include "MyDLLlib.h"
}
If in the function is called in the main as this
printf("version %s\n",Get_Version());
then it works.
However if I add a class with some static methods and a static method makes a call to Get_Version()
const char * ret = Get_Version();
then I get a link error:
Error 1 error LNK2019: unresolved external symbol
"__declspec(dllimport) char * __cdecl Get_Version(void)" (__imp_?Get_Version##YAPADXZ)
referenced in function "private: static class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl ServiceDispatch::decoder_Get_Version(class StringBuffer &)"
(?decoder_Get_Version#ServiceDispatch##CA?AV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##AAVStringBuffer###Z)
D:\devt\CplusPlus\VSTrials\Link_to_MyDLLlib\Link_to_MyDllLib\ServiceDispatch.obj Link_to_MyDLLlib``
I am using the same include.
Any clue as to what I might be doing wrong?
If you have CLASS_DECLSPEC defined always as __declspec(dllimport), this will not work for sure. Look at this sample:
DLL_header.h
#if defined( _BUILD_DLL )
# define DLLAPI __declspec(dllexport) //Export when building DLL
#else
# define DLLAPI __declspec(dllimport) //Import when using in other project
#endif
DLLAPI const char *Get_Version();
DLL_source.cpp
#include "Header.h"
const char *Get_Version()
{
return "1.1.0.4";
}
Build DLL with _BUILD_DLL defined.
Main.cpp
#include "DLL_header.h"
int main()
{
printf("%s\n", Get_Version());
return 0;
}
Build this, with _BUILD_DLL not defined.
In your case, it could be problem with extern "C" - you include header inside extern "C", which declares Get_Version() as having __cdecl linkage. But linker is searching for
__imp_?Get_Version##YAPADXZ
Which is a mangled (C++) name. Is your DLL a C or C++ project? If your DLL is build as C project (not C++), put extern "C" on Get_Version()'s declaration with this #ifdef:
#ifdef __cplusplus
extern "C" {
#endif
DLLAPI const char *Get_Version();
#ifdef __cplusplus
}
#endif
Either way, remove extern "C" from around the #include. Also, check if .lib file for this DLL is attached to project as dependency.

LNK2019: unresolved external symbol in function

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
}

Importing a C DLL's functions into a C++ program

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.