I am a mainly C programmer building a prototype on a Raspberry Pi. I'm making extensive use of some open source C code, but also a Raspberry Pi hardware add on which comes with C++ drivers. So I need them to work together. I did some research and got them to work together by writing a C++ function with an extern "C" declaration, compiling this as a shared library and linking it with my C program.
I need the C++ function to instantiate an object the first time it is called and then to be able to interact with this object on subsequent calls to the function. I was slightly overwhelmed by the instructions for how to create and access C++ objects directly in C, so I tried simply adding "static" before the creation of the object - and interacting with the object through the mediation of the C wrapper. This seems to working perfectly but I'm slightly worried that this is not routinely given as the answer to the "using C++ objects in C" and so I wonder if I am going to end up with unforeseen problems? I don't need my code at this stage to be high quality, but I don't want to end up with segmentation errors because I have done something foolish. Any advice would be really appreciated.
Here is a cut down version to show what I am doing. In this example I create a simple c++ function that takes an int argument from the calling C program. If the argument is 0 it creates the objects and sets all the leds in array to 0. If I call this a second time with the argument = 1, it instructs the same object to light all the red leds. This code works.
#include <string.h>
#include <matrix_hal/everloop.h>
#include <matrix_hal/everloop_image.h>
#include <matrix_hal/matrixio_bus.h>
extern "C" int led_change(int input_from_c)
{
namespace hal = matrix_hal;
static hal::MatrixIOBus bus;
static hal::EverloopImage image1d(18);
static hal::Everloop everloop;
if (input_from_c == 0)
{
if (!bus.Init()) return false;
// this line just resizes the EverloopImage object to the number of LEDs on the board
everloop.Setup(&bus);
// switch off the leds
for (int i=0;i<18;i++)
{
image1d.leds[i].red = 0;
image1d.leds[i].green = 0;
image1d.leds[i].blue= 0;
image1d.leds[i].white = 0;
}
everloop.Write(&image1d);
}
else if (input_from_c == 1)
{
for (int i=0;i<18;i++)
{
image1d.leds[i].red = 100;
image1d.leds[i].green = 0;
image1d.leds[i].blue= 0;
image1d.leds[i].white = 0;
}
everloop.Write(&image1d);
}
return 1;
}
The calling code in C is just
#include <unistd.h>
#include <stdio.h>
int led_change (int);
int i;
void main () {
i = led_change(0);
printf("returned %d\n",i);
sleep(1);
i = led_change(1);
printf("returned second time %d\n",i);
}
Hope this clear. Thanks for any help.
You need to compile and link all your C code as C++ modules. The reverse doesn't work. C doesn't know about constructors to be called for your static objects in c++ modules... so the linker has to understand the c++ calling sequences. C++ language was designed with compatibility of old C code in mind. But C doesn't have that statement in mind when it was designed.
Despite of this, C++ compilers normally can compile also pure C code (in C language mode) so one of these compilers will be valid. It will generate code that can survive in the same program without any problem.
You can have a C code main() function in a c++ program, but always use a c++ linker to link that code into the program.
When "C" code is linked to C++ code using "extern", C++ compilers stop "name mangling" for those C variables or functions, while creating symbol names in object file. For C++ functions, they mangle names to support function overloading.
When static objects are returned from shared objects, they might create problem in multi-threaded programs, like two or more threads modifying the values in the static objects at the same time.
Related
I'm a new programmer,my program is about getting LED on,maybe the simplest in C language,but it is always having _'Delay10ms':function contains unnamed parameter,hoping someone help me to solve it.
here are my words:
#include<reg51.h>
#include<intrins.h>
#define GPIO_LED P2
void Delay10ms(unsigned char time)
{
unsigned char i,j;
for(i=1;i<110*time;i++)
for(j=1;j<110;j++);
}
void main()
{
unsigned char n,i,j;
GPIO_LED=0X01;
while(1)
{
for(n=0;n<7;n++)
{
GPIO_LED=_crol_(GPIO_LED,1);
Delay10ms(50);
}
for(n=0;n<7;n++)
{
GPIO_LED=_cror_(GPIO_LED,1);
Delay10ms(50);
}
}
}
Either <reg51.h> or <intrins.h> probably have standard library includes. One of these library includes contains the standard header function time() that returns the current system time. Because your function parameter's name is time the IDE probably can't figure out what you meant with it and thus it gives you that error/warning. Try renaming your variable.
Also, the return type of main() has never been void (C++), use int.
It has been a Long time gone since I played c, but your code Looks o.k., maybe there is a name conflict ("time")
But there are some more questions:
- Why do you use char (unsigned char = 0..255) instead of classic int? This would be make code more readable.
- What do you expect how relyable your timer could be on a multitasking operating System?
I would implement such a function (if it not exists) as
void MyDelay (unsigned int delay_time)
{
start = MyOs.GiveMeTheTime()
while (MyOs.GiveMeTheTime() - start < delay_time)
{};
}
MyOs and GiveMeTheTime are names chosen by me. You must find out, which functions are available on your System, I am sure, they are.
I suppose, you try to program anything like a raspberry pi. Maybe this link could help:
Example Which Provides Accurate uS Timing
What if I define main as a reference to function?
#include<iostream>
#include<cstring>
using namespace std;
int main1()
{
cout << "Hello World from main1 function!" << endl;
return 0;
}
int (&main)() = main1;
What will happen? I tested in an online compiler with error "Segmentation fault":
here
And under VC++ 2013 it will create a program crashing at run-time!
A code calling the data of the function pointer as a code will be compiled which will immediately crash on launch.
I would also like an ISO C++ standard quote about this.
The concept will be useful if you want to define either of 2 entry-points depending on some macro like this:
int main1();
int main2();
#ifdef _0_ENTRY
int (&main)() = main1;
#else
int (&main)() = main2;
#endif
That's not a conformant C++ program. C++ requires that (section 3.6.1)
A program shall contain a global function called main
Your program contains a global not-a-function called main, which introduces a name conflict with the main function that is required.
One justification for this would be it allows the hosted environment to, during program startup, make a function call to main. It is not equivalent to the source string main(args) which could be a function call, a function pointer dereference, use of operator() on a function object, or construction of an instance of a type main. Nope, main must be a function.
One additional thing to note is that the C++ Standard never says what the type of main actually is, and prevents you from observing it. So implementations can (and do!) rewrite the signature, for example adding any of int argc, char** argv, char** envp that you have omitted. Clearly it couldn't know to do this for your main1 and main2.
This would be useful if you want to define either of 2 entry-points depending on some macro
No, not really. You should do this:
int main1();
int main2();
#ifdef _0_ENTRY
int main() { return main1(); }
#else
int main() { return main2(); }
#endif
This is soon going to become clearly ill-formed, thanks to the resolution of CWG issue 1886, currently in "tentatively ready" status, which adds, among other things, the following to [basic.start.main]:
A program that declares a variable main at global scope or that
declares the name main with C language linkage (in any namespace) is
ill-formed.
What will happen in practice is highly dependent on the implementation.
In your case your compiler apparently implements that reference as a "pointer in disguise". In addition to that, the pointer has external linkage. I.e. your program exports an external symbol called main, which is actually associated with memory location in data segment occupied by a pointer. The linker, without looking too much into it, records that memory location as the program's entry point.
Later, trying to use that location as an entry point causes segmentation fault. Firstly, there's no meaningful code at that location. Secondly, a mere attempt to pass control to a location inside a data segment might trigger the "data execution protection" mechanisms of your platform.
By doing this you apparently hoped that the reference will get optimized out, i.e. that main will become just another name for main1. In your case it didn't happen. The reference survived as an independent external object.
Looks like you already answered the question about what happens.
As far as why, in your code main is a reference/pointer to a function. That is different than a function. And I would expect a segment fault if the code is calling a pointer instead of a function.
I'm unsure if the question is phrased correctly, or if what I want to is possible.
I have an existing GCC application (compiled for a Cortex-M3 if that matters). What I want to do is create a little piece of functionality (just a single method, few methods) that can call into the existing application.
I want to place these few methods at a specific memory location (I know how to do that). What I don't know how to do is get the new application to compile/link with the objects of the existing application.
For instance, my existing application has the function:
int Add(int a, int b);
And new application wants to use it:
int Calculate(int a, int b, int opType)
{
Add(a, b);
}
I have access to all linker, obj, h files, etc.
You can't usually link to executables, only libraries (static or shared) and object files. So, the best advice I can give would be to build the "core" of the first program as a shared library, and link the "front-end" (main) as an executable built against the core shared lib. Then, your second program can also just be a program linked against the shared library.
You can also use dlopen on dynamic executables to link the executable at runtime, and use dlsym to get function pointers for the desired functionality, though this is usually only used if you have no control over the first executable.
Example of the latter (note again that this should be a last resort):
a.c:
#include <stdio.h>
int main() { printf("hello world!\n"); return 42; }
b.c:
#include <stdio.h>
#include <dlfcn.h>
main() {
void *handle = dlopen("a", RTLD_LAZY);
if(!handle) {
printf("failed: %s\n", dlerror());
return -1;
}
int (*amain)() = dlsym(handle, "main");
if(!amain) {
printf("dlsym failed: %s\n", dlerror());
return -1;
}
return amain();
}
Thanks for your input, however I was able to do exactly what I wanted by compiling the new application using the ELF file from the existing application has an input to the Linker by specifying
--just-symbols elffile.elf
If you're using a linux variant, then the answer given by #nneonneo to use dlopen() and dlsym() is the best approach.
However, assuming that you're using another OS (or none at all) and/or you really really need this code to live at a fixed location (for example if you need to shift execution to an address on a specific memory device, eg. if doing flash manipulation), you can use a hard coded function pointer.
Declare a function pointer as follows:
typedef int (*AddFnPtr)(int a, int b);
AddFnPtr MyAddFunction = (AddFnPtr)ADDRESS_OF_YOUR_FUNCTION;
Then call as:
int Calculate(int a, int b, int opType)
{
MyAddFunction(a, b);
}
Note that the linker has no way of knowing if the code that you've put at that location has the right prototype, or even exists - so there is no error checking either at link time or at run time.
You will probably (depending on OS) also need to take steps to map the absolute memory location at which you've put your function into the local processes address space.
I am creating a small C++ wrapper shared library around a Fortran 95 library. Since the Fortran symbols contain . in the symbol name, I have to use dlsym to load the Fortran function into a C++ function pointer.
Currently, I have a bunch of global function pointers in header files:
// test.h
extern void (*f)(int* arg);
and I populate them in the corresponding C++ file:
// test.cc
void (*f))(int* = reinterpret_cast<void(*)(int*>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_");
Questions:
If I do it this way, when are these pointers populated?
Can I assume them to be loaded in my executable that loads this library?
In particular, can I use these functions in statically created objects in my executable or other libraries? Or does this suffer from the static initalization order fiasco?
If the above way is not correct, what is the most elegant way of populating these pointers such that they can be used in static objects in executables and other libraries?
I am using the Sun Studio compiler on Solaris, if that makes a difference, but I would also be interested in a solution for GCC on Linux.
Where does the line
f = reinterpret_cast<void(*)(int*)>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_"));
occur in test.cc? The pointer will be initialized when the line is
executed (which of course depends on when the function which contains it
is called). Or did you mean to write
void (*f)(int* ) = reinterpret_cast<void(*)(int*>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_");
? In this case, the pointer will be initialized during static
initialization. Which means that you still have order of initialization
issues if you try to use the pointers in the constructor of a static
object.
The classical solution for this would be to use some sort of singleton:
struct LibraryPointers
{
void (*f)(int* );
// ...
static LibraryPointers const& instance()
private:
LibraryPointers();
};
LibraryPointers const&
LibraryPointers::instance()
{
static LibraryPointers theOneAndOnly;
return theOneAndOnly;
}
LibraryPointers::LibraryPointers()
: f( reinterpret_cast<void(*)(int*)>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_")) )
, // initialization of other pointers...
{
}
Then wrap the library in a C++ class which uses this structure to get
the addresses of the pointers.
And one last remark: the reinterpret_cast you are trying to do isn't
legal, at least not formally. (I think that both Sun CC and g++ will
accept it, however.) According to Posix, the correct way to get a
pointer to function from dlsym would be:
void (*f)(int* );
*reinterpret_cast<void**>(&f) = dlsym(...);
This doesn't lend itself to initializations, however.
A little background:
I've got a library of C code that is part of larger system (all C). For this particular part of the C library a GUI has to be created which allows users to play around with the options. For the GUI I've chosen QT, since cross-platform support is desired.
I'm using Eclipse and MinGW as IDE and compiler (but I think the question is more language than compiler specific?).
With QT I've created a widget that holds a pointer to a struct implemented in C that contains pointers to several functions that perform the logic of the C library.
//QTWidget.cpp
extern "C" {
#include "c-src/CLogic.h"
//extern char* textHelper;
}
QTWidget::QTWidget(QWidget *parent)
{
//rtw is a struct that contains a function pointer to a member of QTWidget
this->rtw.displayText = &QTWidget::displayText;
this->clogic = CLogic_getInstance(&rtw);
}
//Public SLOT, connected to a button's clicked SIGNAL
void QTWidget::buttonClicked()
{
this->clogic->buttonClicked();
}
void QTWidget::displayText(char *text, int position)
{
//I've tried creating a QString from the char*, but this does not work at all.
//ui.textItem->setText(textHelper);
ui.textItem->setText(text);
}
When the user presses a button in the GUI, the method QTWidget::buttonClicked() is called, which tells the C library to do something. Note the the CLogic struct has a reference to the the QTWidget in the form of a struct RefToWidget which holds a function pointer.
//CLogic.c
static CLogic instance;
void CLogic_buttonClicked()
{
//I've tried several variants here, such as making a global
//char* textHelper = "Hello World";
//that is referenced by using the "extern" keyword in the CPP file above.
instance.rtw->displayText("Hello World", 1);
}
CLogic* CLogic_getInstance(RefToWidget *rtw)
{
instance.rtw = rtw;
instance.buttonClicked = &CLogic_buttonClicked();
}
When debugging this program, I find that all the function calls are executed as intended (when I press a button, the QT slot buttonClicked() is called, the CLogic_buttonClicked() is called, which calls the QTWidget::displayText() as planned, but in this last call the parameters are invalid. The char* text points to 0x1 and claims to be pointing to memory out of bounds, while the int position looks like some random number (uninitialized).
How do I pass this data from C to CPP?
EDIT #Luccas Matteis:
#ifdef __cplusplus
#include "QTWidget.h"
extern "C" {
#endif
struct RefToWidget{
#ifdef __cplusplus
void (QTWidget::*displayLine)(char* text, int lineNumber);
#else
void (*displayLine)(char* text, int lineNumber);
#endif
};
typedef struct RefToWidget RefToWidget;
#ifdef __cplusplus
}
#endif
As said above the function calls behave as expected, but the data is not passed "correctly" (even though that when I look at it, the code seems a bit... weird... ;))
Your problem is not passing the char * from C to C++ but calling a C++ function from C. I presume that CLogic.c is compiled as a C library? If not, can you rename it to CLogic.cpp or use a compiler switch to force it to be compiled as C++ even though it has a C file extension?
If you want a C++ GUI on a C library/system, you need to use proper Model-View-Controller logic. Here the C++ code is the View and the Controller while the C code is the Model (as best as I can tell from your description). You need to make it so you set and get data from the model but the model never calls the View or Controller as you are trying to do.
Think about what you are REALLY trying to do. If you just want to display a static string when the button is pressed, why go to the bother of calling into CLogic.c? If you want to display a string that depends upon the state of the CLogic instance then instead do something like:
void QTWidget::buttonClicked()
{
char *display_text = this->clogic->get_button_click_text();
ui.textItem->setText(display_text);
}
I guess the problem is that the structure holds a pointer to a member function. The member function probably expects the first parameter to be 'this' - the object it refers to. So, in fact what you are seeing in debug as text is the second parameter.
A 'solution' would probably be to do something like "instance.rtw->displayText(instance.rtw, "Hello World", 1)", but have no idea if it is portable etc.
Edit: Saying it explicitly: the 'solution' stated above is just to try and check if this is the problem. As the comments are saying this is a horrible hack that might not work even on the same compiler.
I don't think that you should call a C++ method from C. Normally you need to go through a static method that dereferences a pointer argument