Search code examples
c++cqtqt5

Undefined reference when I'm linking C files in C++ inside Qt framework


Introduction:

I have a C++ project inside the Qt framework, and I have recently created a CAN-bus SAE J1939 library in pure 100% C99 code. The library works very well. I will now import the library into my Qt project in Qt Creator.

Note: The compiler is MinGW 5.15.2

Method:

I have included .h files in C++ with Qt framework by including the line inside my .pro project file.

include(ThirdLibrary/OpenSAEJ1939/OpenSAEJ1939.pri)

Inside the OpenSAEJ1939.pri file, it is written

INCLUDEPATH += $$PWD

Here is my project folder:

Enter image description here

The path ThirdLibrary/OpenSAEJ1939/Open_SAE_J1939/

Enter image description here

So when I created a C++ source file and then added the C source function, I got undefined reference to Open_SAE_J1939_Listen_For_Messages.

#include "Can_Bus_Listen_Thread.h"

CAN_Bus_Listen_Thread::CAN_Bus_Listen_Thread(J1939* j1939, bool* usbMessageAvailable, bool* startCANBusListenThread){
    this->j1939 = j1939;
    this->usbMessageAvailable = usbMessageAvailable;
    this->startCANBusListenThread = startCANBusListenThread;
}

void CAN_Bus_Listen_Thread::run(){
    while(1){
        if(*this->startCANBusListenThread && *this->usbMessageAvailable)
            Open_SAE_J1939_Listen_For_Messages(this->j1939);
        msleep(1);
    }
}

I look inside the C++ header Can_Bus_Listen_Thread.h and I can see that I have imported the C header file from ThirdLibrary/OpenSAEJ1939/Open_SAE_J1939/.

#ifndef CAN_BUS_LISTEN_THREAD_H
#define CAN_BUS_LISTEN_THREAD_H

#include <QThread>
#include <QtSerialPort>
#include "ThirdLibrary/OpenSAEJ1939/Open_SAE_J1939/Open_SAE_J1939.h"

class CAN_Bus_Listen_Thread : public QThread {
public:
    CAN_Bus_Listen_Thread(J1939* j1939, bool* usbMessageAvailable, bool* startCANBusListenThread);
private:
    J1939* j1939;
    bool* startCANBusListenThread;
    bool* usbMessageAvailable;
    void run();
};

#endif // CAN_BUS_LISTEN_THREAD_H

I have successfully included the C header files, but these header files cannot find the C source files. And yes, the Open_SAE_J1939_Listen_For_Messages is surrounded with extern "C" { } here inside Open_SAE_J1939.h.

Have I forgot something? C++ should be able to read C source files if they are surrounded with extern "C" { }

#ifndef OPEN_SAE_J1939_OPEN_SAE_J1939_H_
#define OPEN_SAE_J1939_OPEN_SAE_J1939_H_

/* Layers */
#include "../Open_SAE_J1939/Structs.h"
#include "../SAE_J1939/SAE_J1939-71_Application_Layer/Application_Layer.h"
#include "../SAE_J1939/SAE_J1939-73_Diagnostics_Layer/Diagnostics_Layer.h"
#include "../SAE_J1939/SAE_J1939-81_Network_Management_Layer/Network_Management_Layer.h"

#ifdef __cplusplus
extern "C" {
#endif

/* This functions must be called all the time, or be placed inside an interrupt listener */
void Open_SAE_J1939_Listen_For_Messages(J1939 *j1939);

#ifdef __cplusplus
}
#endif

#endif /* OPEN_SAE_J1939_OPEN_SAE_J1939_H_ */

Solution

  • Here is the solution.

    1. right-click on your project in Qt.
    2. Select "Add existing dictionary"
    3. Mark the dictionary you want to import. Now you are seeing lots of .c and .h files inside the .pro file.

    Hint: Don't use ../../. That can cause troubles. Instead, use the project path instead, e.g.,

    "ThirdLibrary/OpenSAEJ1939/...your_h_files.h"
    

    You don't need the .pri file. Get rid of it.