I want to declare printf function by myself, and try if the code can work.
I looked into the <stdio.h> and found it declared as:
_Check_return_opt_ _CRTIMP int __cdecl printf(_In_z_ _Printf_format_string_ const char * _Format, ...);
Then I found
_Check_return_opt_ defined in <crtdefs.h>
_CRTIMP defined in <crtdefs.h>
_In_z_ _Printf_format_string_ defined in <sal.h>
So my code is as:
#include <crtdefs.h>
#include <sal.h>
_Check_return_opt_ _CRTIMP int __cdecl printf(_In_z_ _Printf_format_string_ const char * _Format, ...);
int main()
{
int a = 100;
printf("%d\n",a);
}
I guess this will work, but it gets an error:
error LNK2019: unresolved external symbol ...
What's wrong with my code? Are there anything I missed in <stdio.h>?
I have already read a question on stackoverflow.
(https://stackoverflow.com/questions/25155631/microsoft-visual-studio-2012-version-of-printf-function-declaration)
It helps, but doesn't solve my problem.
I also learn to know that an extern "C" function works fine. such as:
extern "C" int printf (const char * __format, ...);
But I think this still not accounts for my doubt.
In stdio.h, was the prototype for printf inside an extern "C" {} block? Note that this block could be large and so you might not have noticed it. If so, you need to use extern "C" around your prototype.
The extern "C" should remove your doubt - without that you are compiling the declaration as C++ which doesn't use a linking convention that's the same as C (which is how printf() is compiled in the library).
You can fix the problem using extern "C" or compiling your program as a C program instead of C++ (change the name of the source file to have a .cextension).
Related
This question already has answers here:
What is the effect of extern "C" in C++?
(17 answers)
Closed 1 year ago.
I have a small issue.
I thought that using using extern "C" will turn the C code into C++ code directly.
#ifdef __cplusplus
extern "C" {
#endif
ENUM_J1939_STATUS_CODES CAN_Send_Message(uint32_t ID, uint8_t data[], uint8_t delay);
ENUM_J1939_STATUS_CODES CAN_Send_Request(uint32_t ID, uint8_t PGN[], uint8_t delay);
bool CAN_Read_Message(uint32_t *ID, uint8_t data[]);
#ifdef __cplusplus
}
#endif
But when I placed a class QSerialPort in here
#ifdef __cplusplus
extern "C" {
#endif
#include <QSerialPort>
ENUM_J1939_STATUS_CODES CAN_Send_Message(uint32_t ID, uint8_t data[], uint8_t delay);
ENUM_J1939_STATUS_CODES CAN_Send_Request(uint32_t ID, uint8_t PGN[], uint8_t delay);
bool CAN_Read_Message(uint32_t *ID, uint8_t data[]);
#ifdef __cplusplus
}
#endif
Then I got 500 errors about data types, name space and all kind of C++ keywords that C does not have.
Question:
In QT. I have to make sure that I can use a C++ class inside a .h file and the .h is included inside a .c file. But right now, my QT IDE shows me 500 errors if I do that.
Is there a way for C code to call C++ code or turning the C code into 100% C++ code, whithout renaming the files .c to .cpp?
My goal is to use C++ features from C, by using extern "C" inside the header of the .c file, but it isin't going any well for me.
Edit:
I tried some ways and this does not work. I get 500 errors.
#include <QSerialPort>
#ifdef __cplusplus
extern "C" {
#endif
void QT_USB_set_serial_handler(QSerialPort* serial_port);
ENUM_J1939_STATUS_CODES QT_USB_Transmit(uint32_t ID, uint8_t data[], uint8_t DLC);
void QT_USB_Get_ID_Data(uint32_t *ID, uint8_t data[], bool* is_new_message);
#ifdef __cplusplus
}
This gives only one error.
#ifdef __cplusplus
#include <QSerialPort>
extern "C" {
#endif
void QT_USB_set_serial_handler(QSerialPort* serial_port); <-- complaining here on QSerialPort keyword
ENUM_J1939_STATUS_CODES QT_USB_Transmit(uint32_t ID, uint8_t data[], uint8_t DLC);
void QT_USB_Get_ID_Data(uint32_t *ID, uint8_t data[], bool* is_new_message);
#ifdef __cplusplus
}
This gives no error at all.
#ifdef __cplusplus
#include <QSerialPort>
void QT_USB_set_serial_handler(QSerialPort* serial_port);
extern "C" {
#endif
ENUM_J1939_STATUS_CODES QT_USB_Transmit(uint32_t ID, uint8_t data[], uint8_t DLC);
void QT_USB_Get_ID_Data(uint32_t *ID, uint8_t data[], bool* is_new_message);
#ifdef __cplusplus
}
You use extern "C" { ... } in C++ code, around declarations of external functions which are C functions, not C++ functions.
extern "C" { ... } does not somehow "turn C code into C++ code".
It does not turn C++ code into C code, either.
You use extern "C" { ... } when you have some other function(s) to call, and those other functions are present in source files ending in .c and compiled as C, not C++. extern "C" { ... } makes sure that your C++ compiler passes arguments, generates function calls, emits relocation information, etc., in a way that's compatible with C, not C++.
There's no mechanism (that I know of) to embed arbitrary C code inside a C++ source file, and have it treated as C. And there's even less of a mechanism to embed arbitrary C++ code inside a C source file, and have it treated as C++!
Addendum: I'm somewhat embarrassed that this answer has been upvoted and accepted, since I've just realized it's been only partially correct so far. extern "C" can indeed be used to mark an external function (defined elsewhere) as being named and called using C conventions, as I said. But it can also be used to mark a C++ function (defined "here") as being named and called using C conventions, so that it can be called from a C function elsewhere.
See this other answer for a better explanation of this.
To summarize, I believe there are two almost completely different cases using extern "C":
syntax
function defined
function written in
function called from
caller written in
function declaration
somewhere else
C (or maybe C++)
here
C++
function definition
here
C++
somewhere else
C or C++
In particular, you can call a C function from C++ (first row, the case I was talking about above), but you can also call a C++ function from C (second row, that I tend to forget is even possible). In the second case, when you're calling a C++ function from C, I think you have to make sure that your final compilation uses a C++ compiler, not a C compiler, so that the right run-time support will be provided for the C++ functions that need it.
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.
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
}
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Convert some code from C++ to C
I've got some code that appears to be straight C. When I tell the compiler (I'm using Visual Studio 2008 Express) to compile it as c++, it compiles and links fine. When I try to compile it as C, though, it throws this error:
1>InpoutTest.obj : error LNK2019: unresolved external symbol _Out32#8 referenced in function _main
1>InpoutTest.obj : error LNK2019: unresolved external symbol _Inp32#4 referenced in function _main
The code reads from and writes to the parallel port, using Inpout.dll. I have both Inpout.lib and Inpout.dll. Here's the code:
// InpoutTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
/* ----Prototypes of Inp and Outp--- */
short _stdcall Inp32(short PortAddress);
void _stdcall Out32(short PortAddress, short data);
/*--------------------------------*/
int main(int argc, char* argv[])
{
int data;
if(argc<3)
{
//too few command line arguments, show usage
printf("Error : too few arguments\n\n***** Usage *****\n\nInpoutTest read <ADDRESS> \nor \nInpoutTest write <ADDRESS> <DATA>\n\n\n\n\n");
}
else if(!strcmp(argv[1],"read"))
{
data = Inp32(atoi(argv[2]));
printf("Data read from address %s is %d \n\n\n\n",argv[2],data);
}
else if(!strcmp(argv[1],"write"))
{
if(argc<4)
{
printf("Error in arguments supplied");
printf("\n***** Usage *****\n\nInpoutTest read <ADDRESS> \nor \nInpoutTest write <ADDRESS> <DATA>\n\n\n\n\n");
}
else
{
Out32(atoi(argv[2]),atoi(argv[3]));
printf("data written to %s\n\n\n",argv[2]);
}
}
return 0;
}
I previously asked this question, incorrectly, here.
Any help would be appreciated.
You're trying to link to a C++ function, from C. That doesn't work due to name mangling- the linker doesn't know where to look for your function. If you want to call a C function from C++, you must mark it extern "C". C does not support extern "C++"- as far as I know. One of the other answers says there is. Alternatively, recompile it's source code as C.
Edit: Why ever would you compile as C if you could compile as C++, anyway?
It sounds like Inp32 and Out32 are defined externally in a C++ file/library, so you need to mark them as such so the compiler knows how their names will be mangled:
extern "C++" {
short _stdcall Inp32(short PortAddress);
void _stdcall Out32(short PortAddress, short data);
}
If you need to call a C++ routine from C code, then the C++ routine need to have "C" linkage, which is done by marking the function as extern "C". That needs to be done on the C++ side.
Put the following as the prototypes for Inp32() and Outp32() if you're able to change the existing C++ code. This should be in a header that's included by whatever calls or defined the Inp32() or Outp32() functions - whether C or C++ code:
#ifdef __cplusplus
extern "C" {
#endif
short _stdcall Inp32(short PortAddress);
void _stdcall Out32(short PortAddress, short data);
#ifdef __cplusplus
}
#endif
That will mark those functions as having a C calling convention, and those functions will be callable by either C or C++ code.
If you don't have the ability to change the C++ code, you can create your own C-compatible wrappers for the C++ functions in your own C++ module:
The wrappers.h header file:
// in wrappers.h
// C-callable wrappers
#ifndef WRAPPERS_H
#define WRAPPERS_H
#ifdef __cplusplus
extern "C" {
#endif
short Inp32_wrapper( short PortAddress);
void Out32_wrapper( short PortAddress, short data);
#ifdef __cplusplus
}
#endif
#endif /* WRAPPERS_H */
And, the wrappers.cpp implementation:
// in wrappers.cpp file:
#include "wrappers.h"
// prototypes for the C++ functions - these really should be in a
// header file...
short _stdcall Inp32(short PortAddress);
void _stdcall Out32(short PortAddress, short data);
// implementation of the wrappers
short Inp32_wrapper( short PortAddress)
{
return Inp32( PortAddress);
}
void Out32_wrapper( short PortAddress, short data)
{
Out32( PortAddress, data);
}
Now your C code can #include "wrappers.h" and call the wrapper functions which will simply call the existing C++ functions to do the work.
It doesn't appear to be a compiler error, but rather a linker error. The linker can't find the definitions of Inp32 and Out32. Are you linking to the library that contains the definitions? Did you spell them correctly?
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.