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; }
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 know this.
Calling C function from C++:
If my application was in C++ and I had to call functions from a library written in C. Then I would have used
//main.cpp
extern "C" void C_library_function(int x, int y);//prototype
C_library_function(2,4);// directly using it.
This wouldn't mangle the name C_library_function and linker would find the same name in its input *.lib files and problem is solved.
Calling C++ function from C???
But here I'm extending a large application which is written in C and I need to use a library which is written in C++. Name mangling of C++ is causing trouble here. Linker is complaining about the unresolved symbols. Well I cannot use C++ compiler over my C project because thats breaking lot of other stuff. What is the way out?
By the way I'm using MSVC
You need to create a C API for exposing the functionality of your C++ code. Basically, you will need to write C++ code that is declared extern "C" and that has a pure C API (not using classes, for example) that wraps the C++ library. Then you use the pure C wrapper library that you've created.
Your C API can optionally follow an object-oriented style, even though C is not object-oriented. Ex:
// *.h file
// ...
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
typedef void* mylibrary_mytype_t;
EXTERNC mylibrary_mytype_t mylibrary_mytype_init();
EXTERNC void mylibrary_mytype_destroy(mylibrary_mytype_t mytype);
EXTERNC void mylibrary_mytype_doit(mylibrary_mytype_t self, int param);
#undef EXTERNC
// ...
// *.cpp file
mylibrary_mytype_t mylibrary_mytype_init() {
return new MyType;
}
void mylibrary_mytype_destroy(mylibrary_mytype_t untyped_ptr) {
MyType* typed_ptr = static_cast<MyType*>(untyped_ptr);
delete typed_ptr;
}
void mylibrary_mytype_doit(mylibrary_mytype_t untyped_self, int param) {
MyType* typed_self = static_cast<MyType*>(untyped_self);
typed_self->doIt(param);
}
I would do it in the following way:
(If working with MSVC, ignore the GCC compilation commands)
Suppose that I have a C++ class named AAA, defined in files aaa.h, aaa.cpp, and that the class AAA has a method named sayHi(const char *name), that I want to enable for C code.
The C++ code of class AAA - Pure C++, I don't modify it:
aaa.h
#ifndef AAA_H
#define AAA_H
class AAA {
public:
AAA();
void sayHi(const char *name);
};
#endif
aaa.cpp
#include <iostream>
#include "aaa.h"
AAA::AAA() {
}
void AAA::sayHi(const char *name) {
std::cout << "Hi " << name << std::endl;
}
Compiling this class as regularly done for C++. This code "does not know" that it is going to be used by C code. Using the command:
g++ -fpic -shared aaa.cpp -o libaaa.so
Now, also in C++, creating a C connector:
Defining it in files aaa_c_connector.h, aaa_c_connector.cpp. This connector is going to define a C function, named AAA_sayHi(cosnt char *name), that will use an instance of AAA and will call its method:
aaa_c_connector.h
#ifndef AAA_C_CONNECTOR_H
#define AAA_C_CONNECTOR_H
#ifdef __cplusplus
extern "C" {
#endif
void AAA_sayHi(const char *name);
#ifdef __cplusplus
}
#endif
#endif
aaa_c_connector.cpp
#include <cstdlib>
#include "aaa_c_connector.h"
#include "aaa.h"
#ifdef __cplusplus
extern "C" {
#endif
// Inside this "extern C" block, I can implement functions in C++, which will externally
// appear as C functions (which means that the function IDs will be their names, unlike
// the regular C++ behavior, which allows defining multiple functions with the same name
// (overloading) and hence uses function signature hashing to enforce unique IDs),
static AAA *AAA_instance = NULL;
void lazyAAA() {
if (AAA_instance == NULL) {
AAA_instance = new AAA();
}
}
void AAA_sayHi(const char *name) {
lazyAAA();
AAA_instance->sayHi(name);
}
#ifdef __cplusplus
}
#endif
Compiling it, again, using a regular C++ compilation command:
g++ -fpic -shared aaa_c_connector.cpp -L. -laaa -o libaaa_c_connector.so
Now I have a shared library (libaaa_c_connector.so), that implements the C function AAA_sayHi(const char *name). I can now create a C main file and compile it all together:
main.c
#include "aaa_c_connector.h"
int main() {
AAA_sayHi("David");
AAA_sayHi("James");
return 0;
}
Compiling it using a C compilation command:
gcc main.c -L. -laaa_c_connector -o c_aaa
I will need to set LD_LIBRARY_PATH to contain $PWD, and if I run the executable ./c_aaa, I will get the output I expect:
Hi David
Hi James
EDIT:
On some linux distributions, -laaa and -lstdc++ may also be required for the last compilation command. Thanks to #AlaaM. for the attention
Assuming the C++ API is C-compatible (no classes, templates, etc.), you can wrap it in extern "C" { ... }, just as you did when going the other way.
If you want to expose objects and other cute C++ stuff, you'll have to write a wrapper API.
You will have to write a wrapper for C in C++ if you want to do this. C++ is backwards compatible, but C is not forwards compatible.
export your C++ functions as extern "C" (aka C style symbols), or use the .def file format to define undecorated export symbols for the C++ linker when it creates the C++ library, then the C linker should have no troubles reading it
#include <iostream>
//////////////
// C++ code //
//////////////
struct A
{
int i;
int j;
A() {i=1; j=2; std::cout << "class A created\n";}
void dump() {std::cout << "class A dumped: " << i << ":" << j << std::endl;}
~A() {std::cout << "class A destroyed\n";}
};
extern "C" {
// this is the C code interface to the class A
static void *createA (void)
{
// create a handle to the A class
return (void *)(new A);
}
static void dumpA (void *thisPtr)
{
// call A->dump ()
if (thisPtr != NULL) // I'm an anal retentive programmer
{
A *classPtr = static_cast<A *>(thisPtr);
classPtr->dump ();
}
}
static void *deleteA (void *thisPtr)
{
// destroy the A class
if (thisPtr != NULL)
{
delete (static_cast<A *>(thisPtr));
}
}
}
////////////////////////////////////
// this can be compiled as C code //
////////////////////////////////////
int main (int argc, char **argv)
{
void *handle = createA();
dumpA (handle);
deleteA (handle);
return 0;
}
You can prefix the function declaration with extern “C” keyword, e.g.
extern “C” int Mycppfunction()
{
// Code goes here
return 0;
}
For more examples you can search more on Google about “extern” keyword. You need to do few more things, but it's not difficult you'll get lots of examples from Google.
guys.
I am writing an iOS app in swift, and I need to call some C++ lib. So I've build a simple example on how to bridge between C++ and Swift, and test on an iTouch. I wrapped the C++ interface with extern C. But I can't read the file when I call C++ function. Here is the code.
When I click the button on the iOS device, it needs to call the myFun():
main.swift
#IBAction func button(sender: AnyObject) {
myFun()
}
myFun() is my C++ function, which just reads a local file("hi.c").
DlibFun.cpp
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include "DlibFun.h"
#include <unistd.h>
void myFun(){
char* path = (char*)"/hi.c";
FILE* f = fopen(path, "r");
if(f != NULL){
printf("open it\n");
fclose (f);
}else{
printf("FAIL\n");
}
}
Wrapper the C++ code in C
DlibFun.h
#ifdef __cplusplus
extern "C" {
#endif
int myFun();
#ifdef __cplusplus
}
#endif
photo-Bridging-Header.h
#include "DlibFun.h"
The result is that every time it prints out "FAIL". And any one give me any hint? I have tried the different path, but none of them are correct. Is it possible that my path is wrong? or there is any thicky thing that I don't know?
File folder
As you said, the code in the question is a simple example. I don't think the problem you are asking about, namely the fact that "FAIL" is output, is related to the real difficulties of bridging between C++ and Swift. The C++ function is called correctly, but the file can't be opened, most likely because it isn't there or isn't readable. In fact, I reproduced your example in Xcode, and got the output "open it" as long as the file was available; otherwise it would be "FAIL," as in your case.
Because DlibFun.cpp includes DlibFun.h, where myFun() is declared extern "C", the C++ compiler will compile myFun() to have C linkage, meaning it can be called from C and Swift. When Swift sees myFun() through the bridging header, it just treats it as a C function and calls it as such.
In a real-world situation, myFun() would be implemented in some C++ library and compiled using a C++ compiler, giving it C++ linkage, so just creating a header in Xcode, declaring myFun() extern "C", and then including the header in the bridge won't help. The build will fail with a link error.
To call the C++ library function myFun() you can write a wrapper as follows:
///////////////////
// File DlibFunW.h:
#ifndef DlibFunW_h
#define DlibFunW_h
// Because this is a C file for use by Swift code, via
// the bridge header, we don't need #ifdef __cplusplus.
// And because myFunW() was marked extern "C" in our C++
// wrapper, it's just a C function callable from Swift.
void myFunW();
#endif /* DlibFunW_h */
////////////////////
// File DlibFun.cpp:
#include "DlibFun.h"
// This file is C++ because it calls myFun(), which is
// a function with C++ linkage.
// This code is visible only to the C++ compiler, so
// we don't need #ifdef __cplusplus
extern "C" void myFunW() { myFun(); }
Now we don't need extern "C" in DlibFun.h, since myFun() has C++ linkage, as a real-world C++ library function would. The bridging header is now just
#include "DlibFunW.h"
and Swift calls myFunW() instead of myFun().
Of course, this is a very simple example dealing only with the C vs. C++ linkage problem. A real-world C++ function would take parameters and return values, often of pointer, struct, and class types, and dealing with those is a completely different can of worms. Here on StackOverflow you'll find plenty of info on that. Some questions I'd recommend:
Swift converts C's uint64_t different than it uses its own UInt64 type
How do I get a specific bit from an Integer in Swift?
Converting inout values to UnsafeMutablePointer<Unmanaged<TYPE>?>
Is it possible to convert a Swift class into C void* pointer?
Can I mix Swift with C++? Like the Objective - C .mm files
Hope you find useful info there, all the best!
I'm running into a mysterious situation with the GCC compiler. So I've got the following files:
//main.cpp
#include "mleak_cpp.h"
int main(int argc, char* argv[])
{
foo();
__memory_malloc(10,"hello",5);
return 0;
}
//mleak_cpp.h
......
void foo(void);
void* __memory_malloc(size_t size, const char* file, int line);
//mleak_cpp.cpp
//definitions of the functions;
void foo(void){printf("foo\n");
void* __memory_malloc(size_t size, const char* file, int line){
printf("%s,%d\n",file,line);
InitDoubleLinkList();
void* p = malloc(size);
if(p == NULL)
return NULL;
__DuLinkList* pListNode;
pListNode = (__DuLinkList*)malloc(sizeof(__DuLinkList));
pListNode->address = p;
pListNode->memorysize = size;
pListNode->file = file;
pListNode->line = line;
InsertBlockToList(pListNode);
return p;
}
For some reason, the call to void foo(void) is fine, but the call to "__memory_malloc" goes down with a linker error, "undefined reference" blah blah. What's the difference between the two functions that causes the different behaviour?
I tried adding "extern C" to the "#include" directive, so main.cpp reads:
extern "C"{
#include "mleak_cpp.h"
}
and adding the keyword "extern" before the declarations of the functions, and this time the call to "foo()" fails too with the same error.
I appreciate any help from you guys
You're placing extern "C" in the wrong place.
If main.c is truly a C file, and mleak_cpp.cpp is truly a C++ function, then you need to put an extern "C" ahead of the definition of __memory_malloc() like so:
extern "C" void* __memory_malloc(size_t size, const char* file, int line){
// ...
}
If you put extern "C" in the mleak_cpp.h file, it needs to be guarded:
#ifdef __cplusplus
extern "C" {
#endif
/* ... body of header ... */
#ifdef __cplusplus
}
#endif
Also, it's not clear why foo works in your example above, when one file calls __foo() but the other file defines foo(). I assume something more is at play, such as an editing error in your question.
extern "C" is for C++, not C, and tells it that the function's name shouldn't be mangled. In C code, you should never see this. Generally, you put it in header files, and you guard it, like this:
#ifdef __cplusplus
extern "C" {
#endif
/* C and C++ compatible header file body here */
#ifdef __cplusplus
} /* end extern "C" */
#endif
If you do it this way though, you need to include the header file in both your C and C++ files, so that the C++ compiler knows to use C linkage.
You can put the extern "C" in front of the function definition in C++ instead and leave it out of the header, but this only works if you only include the headers in C code, so it's recommended to do it the way I pointed out above.
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?