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?
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 to use a third-party C++ library (that I can not change) and call its API from C code.
For most of the library APIs I use a wrapper as explained in this post:
How to call C++ function from C?
But there is one API that takes a variable number of arguments.
Here is its definition (from the header file provided with the library):
void consoleDebug(char* format, ...);
I do not see how I can write the wrapper function for this API.
I tried this but it does not work:
extern "C" {
void wrapper_consoleDebug(char * format, ...)
{
va_list argptr;
va_start(argptr,format);
consoleDebug(format, argptr);
va_end(argptr);
}
}
Any idea is welcome! Thanks!
problem of call c++ functions from c that it used different decoration.
all next for cl.exe (msvc) + link.exe toolset, but think other compiler/linkers have analog features
for example when you compile in c++ function
void consoleDebug(char* format, ...)
in obj (or static lib) file will be ?consoleDebug##YAXPEADZZ symbol.
but when you use the same function from c unit - in object file will _consoleDebug (for x86) or consoleDebug (other platforms)
if we declare in c file
void consoleDebug(char* format, ...)
and do call - in obj will be stored that external symbol consoleDebug (or _consoleDebug) used. when linker will be build code - it will search - where is [_]consoleDebug actually defined (in all obj and lib passed to him) and founf nothing - no such symbol. as result we got error unresolved external symbol [_]consoleDebug
solution here in undocumented linker option /alternatename :
/alternatename:sym1=sym2
with this we say to linker (link.exe) if he need sym1 symbol and can not found it - try use sym2 instead. with this we can create next solution:
1 - we need know exactly symbol name in c++ - we can get it with __FUNCDNAME__ macro:
for example:
#define _GET_NAMES_
#ifdef _GET_NAMES_
void consoleDebug(char* format, ...)
{
#pragma message(__FUNCSIG__ ";\r\n")
#pragma message("__pragma(comment(linker, \"/alternatename:" __FUNCTION__ "=" __FUNCDNAME__ "\"))")
}
#endif // _GET_NAMES_
this is temporary, fake code, need only for print __FUNCDNAME__
then in c file we declare
void __cdecl consoleDebug(char *,...);
#ifdef _X86_
__pragma(comment(linker, "/alternatename:_consoleDebug=?consoleDebug##YAXPADZZ"))
#else
__pragma(comment(linker, "/alternatename:consoleDebug=?consoleDebug##YAXPEADZZ"))
#endif
and can free use consoleDebug
in case we have multiple functions in c++ with same short name, say
void consoleDebug(char* format, ...);
void consoleDebug(wchar_t* format, ...);
this is also easy work, need only bit different name this 2 api in c code:
void __cdecl consoleDebugA(char *,...);
#ifdef _X86_
__pragma(comment(linker, "/alternatename:_consoleDebugA=?consoleDebug##YAXPADZZ"))
#else
__pragma(comment(linker, "/alternatename:consoleDebugA=?consoleDebug##YAXPEADZZ"))
#endif
void __cdecl consoleDebugW(wchar_t *,...);
#ifdef _X86_
__pragma(comment(linker, "/alternatename:_consoleDebugW=?consoleDebug##YAXPA_WZZ"))
#else
__pragma(comment(linker, "/alternatename:consoleDebugW=?consoleDebug##YAXPEA_WZZ"))
#endif
after this we can simply call like
consoleDebugA("str %u\n", 1);
consoleDebugW(L"str %u\n", 2);
from c code.
no any shim/wrapper code need with this. in case you use not cl/link but other tool-chain and can not found analog of /alternatename name option - possible use asm file for create single jmp shim. say for x64
extern ?consoleDebug##YAXPEADZZ:proc
extern ?consoleDebug##YAXPEA_WZZ:proc
_TEXT segment 'CODE'
consoleDebugA proc
jmp ?consoleDebug##YAXPEADZZ
consoleDebugA endp
consoleDebugW proc
jmp ?consoleDebug##YAXPEA_WZZ
consoleDebugW endp
_TEXT ENDS
END
Thanks for your help!
I tried the suggestion from Sam Varshavchik and it works (at least in my case)! More precisely, here is what I did:
// wrapper.cpp
extern "C" { void (*wrapper_consoleDebug)(char * format, ...) = consoleDebug;}
// wrapper.h
extern void (*wrapper_consoleDebug)(char * format, ...);
// C file
#include "wrapper.h"
// in my code
wrapper_consoleDebug("my logger is %s","great");
I did not try the other suggestions yet, but I guess they would work too.
Thanks again!
How should I call a C++ function (no classes involved) from a Swift file?
I tried this:
In someCFunction.c:
void someCFunction() {
printf("Inside the C function\n");
}
void aWrapper() {
someCplusplusFunction();
}
In someCpluplusfunction.cpp:
void someCplusplusFunction() {
printf("Inside the C++ function");
}
In main.swift:
someCFunction();
aWrapper();
In Bridging-Header.h:
#import "someCFunction.h"
#import "someCplusplusFunction.h"
I found this answer very informative, but still I cannot make it work.
Could you point me in the right direction?
Thanks!
What does the header look like?
If you want to explicitly set the linking type for C-compatible functions in C++, you need to tell the C++ compiler so:
// cHeader.h
extern "C" {
void someCplusplusFunction();
void someCFunction();
void aWrapper();
}
Note that this isn't valid C code, so you'd need to wrap the extern "C" declarations in preprocessor macros.
On OS X and iOS, you can use __BEGIN_DECLS and __END_DECLS around code you want linked as C code when compiling C++ sources, and you don't need to worry about using other preprocessor trickery for it to be valid C code.
As such, it would look like:
// cHeader.h
__BEGIN_DECLS
void someCplusplusFunction();
void someCFunction();
void aWrapper();
__END_DECLS
EDIT: As ephemer mentioned, you can use the following preprocessor macros:
// cHeader.h
#ifdef __cplusplus
extern "C" {
#endif
void someCplusplusFunction();
void someCFunction();
void aWrapper();
#ifdef __cplusplus
}
#endif
I am trying to write and test a dll file in C++ that I can call whenever I want filesystem level access to things. I am currently having a huge headache when trying to access the methods in this dll in C++. Strangely enough, I was able to call the code in a separate C# program with little trouble, but I want to get an understanding of how dll interaction works in C++.
And this is the .cpp for my dummy executable that should only call my "newMain" test method.
// dummy.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
//#pragma comment(lib,"visa32.lib")
#pragma message("automatic link to adsInterface.dll")
#pragma message(lib, "adsInterface.lib"
extern "C" int __stdcall newMain();
int _tmain(int argc, _TCHAR* argv[])
{
newMain();
std::string i;
std::cin >> i
return 0;
}
The problem is, when I run it I get this error:
error LNK2019: unresolved external symbol _newMain#0 referenced in function _wmain
error LNK1120: 1 unresolved externals
Here is the .h for adsInterface:
// adsInterface.h
#ifndef ADSINTERFACE_H
#define ADSINTERFACE_H
/* //save this for later i have no clue how this really works.
#ifdef ADSAPI_EXPORTS
#define ADSAPI __declspec(dllexport)
#else
#define ADSAPI __declspec(dllexport)
#endif
*/
namespace ADSInterface
{
//test method. should print to console.
__declspec(dllexport) int __stdcall newMain();
void hello();
}
#endif
and here is my .cpp for adsInterface:
// adsInterface.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "adsInterface.h"
#include <iostream>
namespace ADSInterface
{
/* this is where the actual internal class and other methods will go */
void hello()
{
std::cout << "hello from the DLL!" << std::endl;
}
__declspec(dllexport) int __stdcall newMain()
{
hello();
return 0;
}
}
I'll also include the .def file i used when compiling the dll:
; adsInterface.def - defines exports for adsInterface.dll
LIBRARY ADSINTERFACE
;DESCRIPTION 'A C++ dll that allows viewing/editing of alternate data streams'
EXPORTS
newMain #1
Strangely enough, I was able to import the method in C# with this line (I did not have to include a .lib file either):
[DllImport("./adsInterface.dll")] private static extern void newMain();
And it ran when I called it normally:
newMain();
I've been reading many different guides on how to import dll functions, and I've reached the point where I think I'm just mangling together different ways of importation between the languages and just making a mess of things. If anyone is able to provide some insight on how I should be importing dll methods in C++ that would be much appreciated.
delete this declaration:
extern "C" int __stdcall newMain();
and call ADSInterface::newMain() from _tmain.
In the posted code you did not define anything matching that declaration, did you?
Alternatively make the implementation calling the other one, or drag the one from namespace to global.
I'm working on a C++ project that implements C code and I'm stuck on a segmentation fault. The segfault occures when I try to access a global C variable in my C++ code.
Overview of the code:
I have a single c file called video_stage.c with the following code snippet:
#include "video_stage.h"
uint8_t* pixbuf_data = NULL; //pointer to video buffer
vp_os_mutex_t video_update_lock = PTHREAD_MUTEX_INITIALIZER;
C_RESULT output_gtk_stage_transform( void *cfg, vp_api_io_data_t *in, vp_api_io_data_t *out)
{
vp_os_mutex_lock(&video_update_lock);
/* Get a reference to the last decoded picture */
pixbuf_data = (uint8_t*)in->buffers[0];
vp_os_mutex_unlock(&video_update_lock);
return (SUCCESS);
}
This function is periodically called by other C code and updates the pixbuf_data pointer witch points to an RGB videoframe.
It's header file video_stage.h:
#ifndef _IHM_STAGES_O_GTK_H
#define _IHM_STAGES_O_GTK_H
#ifdef __cplusplus
extern "C" {
#endif
#include <config.h>
#include <VP_Api/vp_api_thread_helper.h>
#include <VP_Api/vp_api.h> //hier zit vp_os_mutex in geinclude
PROTO_THREAD_ROUTINE(video_stage, data);
#ifdef __cplusplus
}
#endif
extern uint8_t* pixbuf_data;
extern vp_os_mutex_t video_update_lock;
#endif // _IHM_STAGES_O_GTK_H
The header file contains the extern declaration of the pixbuf_data pointer.
And here the cpp file: device.cc:
#include <iostream>
#include "video_stage.h"
int ardrone_update(ardrone_t *d)
{
uint8_t x;
x = pixbuf_data[0]; //no problem here, this is executed
std::cout << 5 << std::endl; //this is executed too
std::cout << x << std::endl; //segfault occures here
}
When the function in the cpp file is called (by other cpp code), a segfault occures at the cout instruction that prints x.
When I do a printf of the first element of the buffer in the c file, I get what I expect.
I'm sure it has something to do with the mixing of c and c++ code, but according to my research I've done the stuff to make both c and c++ code compatible here.
In C++ code pixbuf_data defined in a C source must be declared with C linkage:
extern "C" uint8_t* pixbuf_data;
Without extern "C" the C++ code must not link, unless there is another (duplicate) definition of pixbuf_data with C++ linkage.
get yourself a debugger and run your program under that. The tracing code does not tell you at all where the segfault appears, IO is slow.
In the code that you show us, you don't seem to allocate memory for pixbuf_data. Anything can happen when you access that without assigning a valid pointer to it.
I am trying to share variable between C project and c++ project. but when i build my solution i got "error LNK2001: unresolved external symbol "struct configuration g_conf ". This what i did:
==== In C project ==
I create a header file and on it i create my struct
typedef struct{ int maxUser; }Configuration;
extern Configuration conf;
==== In C++ project =======
In the main file :
#include "../ProjectC/header.h"
int main(){ conf.maxUser = 10; }