October 25, 2011

justforfun justforfun
Lab Rat
27 posts

How to call self made C function in Qt?

 

Hi, I need to use C to make a function and then be called in Qt. And I tried to compile the C funtion to be a static or dynamic lib first, then call it in Qt. But I failed.

Can anyone help to analyse the reason why it always tell me ‘ ‘sum2’ was not declared in this scope’. If I change the source code to call sleep(1), it can succeed. But why my static lib fails, although I set the path to the g++ correctly already?
Thanks!

To generate the static lib:

  1. gcc -c sum.c
  2. ar -rc libsum.a sum.o

The make under my scratchbox output is below: As you can see, I put the static lib path there ‘-I. libsum.a’
> make

  1. g++ -c -pipe -O3 -g -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/linux-g++-gles2 -I. -I/targets/FREMANTLE_ARMEL/usr/include/qt4/QtCore -I/targets/FREMANTLE_ARMEL/usr/include/qt4/QtGui -I/targets/FREMANTLE_ARMEL/usr/include/qt4 -I. -I. -I. libsum.a -o mainwindow.o mainwindow.cpp
  2. mainwindow.cpp: In member function 'int MainWindow::setValue(int)':
  3. mainwindow.cpp:24: error: 'sum2' was not declared in this scope
  4. mainwindow.cpp: At global scope:
  5. mainwindow.cpp:20: warning: unused parameter 'duty_value'
  6. make: *** [mainwindow.o] Error 1

The C function for test is below. sum.c and sum.h

> cat sum.c

  1. sum2(int a, int b)
  2. {return a+b;}

> cat sum.h

  1. int sum2(int a, int b);

The Qt cpp and header files are below.

[sbox-FREMANTLE_ARMEL: ~/LED_Driving] > cat mainwindow.cpp

  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. #include <QtCore>
  4.  
  5. MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
  6.     ui(new Ui::MainWindow)
  7. {
  8.     ui->setupUi(this);
  9.     QTimer *timer = new QTimer(this);
  10.     connect(timer, SIGNAL(timeout()), this, SLOT(timerUpDate()));
  11.     timer->start(20); //20ms one time
  12. }
  13.  
  14. void MainWindow::timerUpDate()
  15. {
  16.     connect(ui->horizontalSlider, SIGNAL(valueChanged(int)),
  17.                  this, SLOT(setValue(int)));
  18. }
  19.  
  20. int MainWindow::setValue(int duty_value)
  21. {
  22.   // gpio(duty_value);
  23.   // sleep(1);
  24.   return sum2(8,7);
  25. }
  26.  
  27. MainWindow::~MainWindow()
  28. {
  29.     delete ui;
  30. }

> cat mainwindow.h

  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3.  
  4. #include <QMainWindow>
  5.  
  6. namespace Ui {
  7.     class MainWindow;
  8. }
  9.  
  10. class MainWindow : public QMainWindow
  11. {
  12.     Q_OBJECT
  13.  
  14. public:
  15.     explicit MainWindow(QWidget *parent = 0);
  16.     ~MainWindow();
  17.  
  18. public slots:
  19.     int setValue(int);
  20.  
  21. private:
  22.     Ui::MainWindow *ui;
  23.     void timerUpDate();
  24. };
  25.  
  26.  
  27. #endif // MAINWINDOW_H

8 replies

October 25, 2011

mlong mlong
Mad Scientist
1517 posts

Are you including your sum.h header file so that your C++ code knows about your function?

Also, take a look here [parashift.com] for some more important information you will need.

 Signature 

Senior Software Engineer
AccuWeather Enterprise Solutions
/* My views and opinions do not necessarily reflect those of my employer.  Void where prohibited. */

October 25, 2011

justforfun justforfun
Lab Rat
27 posts

Yes, I tried to include sum.h in mainwindow.h but still failed and got below output of ‘make’.

> make

  1. > make
  2. /usr/bin/uic mainwindow.ui -o ui_mainwindow.h
  3. g++ -c -pipe -O3 -g -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/linux-g++-gles2 -I. -I/targets/FREMANTLE_ARMEL/usr/include/qt4/QtCore -I/targets/FREMANTLE_ARMEL/usr/include/qt4/QtGui -I/targets/FREMANTLE_ARMEL/usr/include/qt4 -I. -I. -o main.o main.cpp
  4. g++ -c -pipe -O3 -g -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/targets/FREMANTLE_ARMEL/usr/share/qt4/mkspecs/linux-g++-gles2 -I. -I/targets/FREMANTLE_ARMEL/usr/include/qt4/QtCore -I/targets/FREMANTLE_ARMEL/usr/include/qt4/QtGui -I/targets/FREMANTLE_ARMEL/usr/include/qt4 -I. -I. -I. -L. libsum.a -o mainwindow.o mainwindow.cpp
  5. mainwindow.cpp: In member function 'int MainWindow::setValue(int)':
  6. mainwindow.cpp:26: error: 'sum2' was not declared in this scope
  7. mainwindow.cpp: At global scope:
  8. mainwindow.cpp:22: warning: unused parameter 'duty_value'
  9. make: *** [mainwindow.o] Error 1

And let’s see another trial. With below program and the libsum.a, it can run normally without the header (sum.h) included.
> cat testsum.c

  1. #include <stdio.h>
  2.  
  3. int main()
  4. { printf("%d\n", sum2(8, 7));
  5.   return 0;
  6. }

then compile

  1. > gcc testsum.c -I. libsum.a -o testsum

then run

  1. > ./testsum
  2. 15

So why this testsum.c C code can call the lib while the Qt code cannot call it?

October 25, 2011

koahnig koahnig
Mad Scientist
2193 posts

justforfun wrote:

The C function for test is below. sum.c and sum.h

> cat sum.c

  1. sum2(int a, int b)
  2. {return a+b;}

> cat sum.h

  1. int sum2(int a, int b);

If this is all you have implemented in your files, it might be a little too minimalistic.

One should at least include the header file in the source file. So, this looks a little better:

  1. #include "sum.h"
  2.  
  3. int sum2(int a, int b)
  4. {
  5.      return a+b;
  6. }

Note, that I have declared also the return type. You should have at least seen a number of warnings through compilation.

No, obviously you have not included sum.h in your code where you are using function sum2.

You may add the header in mainwindow.cpp

  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. #include <QtCore>
  4. #include "sum.h"
  5.  
  6. MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
  7.     ui(new Ui::MainWindow)
  8. {
  9.     ui->setupUi(this);
  10.     QTimer *timer = new QTimer(this);
  11.     connect(timer, SIGNAL(timeout()), this, SLOT(timerUpDate()));
  12.     timer->start(20); //20ms one time
  13. }
  14.  
  15. void MainWindow::timerUpDate()
  16. {
  17.     connect(ui->horizontalSlider, SIGNAL(valueChanged(int)),
  18.                  this, SLOT(setValue(int)));
  19. }
  20.  
  21. int MainWindow::setValue(int duty_value)
  22. {
  23.   // gpio(duty_value);
  24.   // sleep(1);
  25.   return sum2(8,7);
  26. }
  27.  
  28. MainWindow::~MainWindow()
  29. {
  30.     delete ui;
  31. }

I assume your code may be compilable now. However, I have not tried it.

The things, you are fighting with, are C/C++ basics. It would be probably more helpful for you to work through a C/C++ tutorial in more detail before you are digging into Qt.

October 25, 2011

justforfun justforfun
Lab Rat
27 posts

Thank you for your reply!

Now the make output is below

  1. ...
  2. mainwindow.o: In function `MainWindow::setValue(int)':
  3. /home/maemo/LED_Driving/mainwindow.cpp:33: undefined reference to `sum2(int, int)'
  4. collect2: ld returned 1 exit status
  5. make: *** [LED_Driving] Error 1

In fact I know those points you mentioned, and I tried before this post. But the test result shows it is not as easy as it looks. I am still wondering how to solve it…

October 25, 2011

peppe peppe
Ant Farmer
1026 posts

I think you should study the basics of C programming, namely how the compilation and linking processes work…

That undefined reference error means that the linker did not see a definition for that function (symbol). Are you sure you’re linking against the object files that contain the implementation of sum2?

 Signature 

Software Engineer
KDAB (UK) Ltd., a KDAB Group company

October 25, 2011

Lukas Geyer Lukas Geyer
Dinosaur Breeder
2074 posts
mlong wrote:
Also, take a look here [parashift.com] for some more important information you will need.

Have you read and followed what’s written there? You usually cannot just link C and C++ code without any further preparations.

October 25, 2011

mkoskim mkoskim
Lab Rat
31 posts

You need to use extern “C” when including C headers to C++. Usually you write your C headers (which you think might be used in C++ projects) like this:

  1. #ifdef __cplusplus
  2. extern "C" {
  3. #endif
  4.  
  5. int mySum(int a, int b);
  6. ...
  7.  
  8. #ifdef __cplusplus
  9. }
  10. #endif

In general, mixing C and C++ is very easy. Just remember (1) using extern “C”, (2) compiling C files with C (not C++) compilers. If you use C++ compiler, and want it to produce “C-style” libraries (which can be used by many different languages, e.g. C++ and Python), use extern “C” to use C-style naming convention. You find more information about this topic easily from Internet.

October 26, 2011

justforfun justforfun
Lab Rat
27 posts

Thank you everyone! mkoskim, you are right. I succeeded with the method you mentioned. I will do some further test to learn more.

 
  ‹‹ font size change for right click menu items and tooltip font change for mainwindow close, min, max buttons      [Solved]Rowcount Tableview ››

You must log in to post a reply. Not a member yet? Register here!