undefined reference to `__imp__ZN9dynamixel11PortHandler14getPortHandlerEPKc', which should stand for dynamixel::PortHandler :: getPortHandler(char const*)
-
Hello, I have this error message:
D:\The arms\prog\Palan prog\Mesure_graph_palan\com.cpp:5: error: undefined reference to `__imp__ZN9dynamixel11PortHandler14getPortHandlerEPKc' debug/com.o: In function `com::com(char const*, int, QObject*)': D:\The arms\prog\Palan prog\build-Mesure_graph_palan-Desktop_Qt_5_15_2_MinGW_64_bit-Debug/../Mesure_graph_palan/com.cpp:5: undefined reference to `__imp__ZN9dynamixel11PortHandler14getPortHandlerEPKc'
For this class:
#ifndef COM_H #define COM_H #include <QObject> #include <QApplication> #include <dynamixel_sdk.h> #include <QSerialPort> class com : public QObject { public: explicit com(char const* port_name, int baudRate, QObject *parent = nullptr); void read_dxl(); void write_dxl(); dynamixel::PortHandler *m_portHandler; dynamixel::PacketHandler *m_packetHandler; }; #endif // COM_H
#include "com.h" com::com( char const* port_name, int baudRate, QObject *parent) : QObject(parent) { m_portHandler = dynamixel::PortHandler :: getPortHandler(port_name); m_portHandler->setBaudRate(baudRate); m_packetHandler = dynamixel::PacketHandler::getPacketHandler(2.0); uint8_t a=1; m_packetHandler->getRxPacketError(a); }
The pro file:
QT += core gui QT += serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++17 # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ app.cpp \ data.cpp \ main.cpp \ mainwindow.cpp\ com.cpp HEADERS += \ app.h \ data.h \ mainwindow.h\ com.h FORMS += \ mainwindow.ui # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target win32:CONFIG(release, debug|release): LIBS += -L/D:/Python/Library/Dynamixel_SDK/DynamixelSDK-3.7.31/c++/build/win64/output/-ldxl_x64_cpp else:win32:CONFIG(debug, debug|release): LIBS += -L/D:/Python/Library/Dynamixel_SDK/DynamixelSDK-3.7.31/c++/build/win64/output/-ldxl_x64_cpp else:unix: LIBS += -L/D:/Python/Library/Dynamixel_SDK/DynamixelSDK-3.7.31/c++/build/win64/output/-ldxl_x64_cpp INCLUDEPATH += $$PWD/'../../../../Python/Library/Dynamixel_SDK/DynamixelSDK-3.7.31/c++/include/dynamixel_sdk' DEPENDPATH += $$PWD/'../../../../Python/Library/Dynamixel_SDK/DynamixelSDK-3.7.31/c++/include/dynamixel_sdk'
PortHandler ( and everything related to the dynamixel_sdk.h) come from the dynamixel SDK, which was working fine on a project I did with Qt on a raspberry Pi a while ago. This code is pretty much a copy paste from that older one.
I also tried to manually copy paste every .h and .cpp files and running it without relying on a library, but it's still returning me the same error message.
Does anyone see the issue?
-
@Christian-Ehrlicher nice guess!
I just checked the .zip file, sure enough there's a .llib and a .dll in there, in DynamixelSDK-3.7.31\c++\build\win64, but a dead giveaway is that the directory contains a dxl_x64_cpp.sln file. Stringdumping the dxl_x64_cpp.lib, the output shows:
__imp_?getPortHandler@PortHandler@dynamixel@@SAPEAV12@PEBD@Z
which is Microsoft flavored name decoration (and the dxl_x64_cpp.dll has a dependency on VCRUNTIME140.dll :-(So to get a working app: either switch a MSVC compiler or rebuild the Dynamixel SDK using MinGW.
-
You should also link against a lib which you're using -> LIBS
-
@Christian-Ehrlicher I should, but it does not seem to help my case.
-
@Factao
Is it only thedynamixel::PortHandler :: getPortHandler()
which is an "undefined reference", no others? E.g. thedynamixel::PacketHandler::getPacketHandler()
resolves OK?Because looking at https://emanual.robotis.com/docs/en/software/dynamixel/dynamixel_sdk/api_reference/cpp/cpp_porthandler/#cpp-porthandler I see
getPortHandler Gets a child class (PortHandlerLinux or PortHandlerWindows) instance
listed in the first Methods table and then never appear again documented on that page, where all other methods are. That seems odd to me, though I haven't used their product/documentation. Could they have removed that from the libraries but failed to remove it form the
.h
file? Just a thought....Otherwise go try a tool on their supplied
.lib
files to find where that symbol is/is supposed to be? -
@JonB said in undefined reference to `__imp__ZN9dynamixel11PortHandler14getPortHandlerEPKc', which should stand for dynamixel::PortHandler :: getPortHandler(char const*):
listed in the first Methods table and then never appear again documented on that page, where all o
First of all, which tool are you reffering to? I must say that I am more of a mechanical type of guy than an accomplished programmer.
As for the error, no, unfortunately. I have the same kind of error for dynamixel::PacketHandler::getPacketHandler().
As for the your hypothesis, the .h is within the include folder, within the sdk if you download it.
Alternatively, here is port_handler.h, that was supposedly used for this library. If you need more details or the .cpp, I invite you to download the sdk, otherwise this thread is gonna get bloated with code.If it may help, the lines "m_portHandler->setBaudRate(baudRate); " and "m_packetHandler->getRxPacketError(a);" are not getting error and also use the said library. I also tried compiling a similar code on Code::Block, but I also get these errors.
/******************************************************************************* * Copyright 2017 ROBOTIS CO., LTD. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ //////////////////////////////////////////////////////////////////////////////// /// @file The file for port control /// @author Zerom, Leon (RyuWoon Jung) //////////////////////////////////////////////////////////////////////////////// #ifndef DYNAMIXEL_SDK_INCLUDE_DYNAMIXEL_SDK_PORTHANDLER_H_ #define DYNAMIXEL_SDK_INCLUDE_DYNAMIXEL_SDK_PORTHANDLER_H_ #if defined(__linux__) #define WINDECLSPEC #elif defined(__APPLE__) #define WINDECLSPEC #elif defined(_WIN32) || defined(_WIN64) #ifdef WINDLLEXPORT #define WINDECLSPEC __declspec(dllexport) #else #define WINDECLSPEC __declspec(dllimport) #endif #elif defined(ARDUINO) || defined(__OPENCR__) || defined(__OPENCM904__) #define WINDECLSPEC #endif #ifdef __GNUC__ #define DEPRECATED __attribute__((deprecated)) #elif defined(_MSC_VER) #define DEPRECATED __declspec(deprecated) #else #pragma message("WARNING: You need to implement DEPRECATED for this compiler") #define DEPRECATED #endif #include <stdint.h> namespace dynamixel { //////////////////////////////////////////////////////////////////////////////// /// @brief The class for port control that inherits PortHandlerLinux, PortHandlerWindows, PortHandlerMac, or PortHandlerArduino //////////////////////////////////////////////////////////////////////////////// class WINDECLSPEC PortHandler { public: static const int DEFAULT_BAUDRATE_ = 57600; ///< Default Baudrate //////////////////////////////////////////////////////////////////////////////// /// @brief The function that gets PortHandler class inheritance /// @description The function gets class inheritance (PortHandlerLinux / PortHandlerWindows / PortHandlerMac / PortHandlerArduino. //////////////////////////////////////////////////////////////////////////////// static PortHandler *getPortHandler(const char *port_name); bool is_using_; ///< shows whether the port is in use virtual ~PortHandler() { } //////////////////////////////////////////////////////////////////////////////// /// @brief The function that opens the port /// @description The function calls PortHandlerLinux::setBaudRate() to open the port. /// @return communication results which come from PortHandlerLinux::setBaudRate() //////////////////////////////////////////////////////////////////////////////// virtual bool openPort() = 0; //////////////////////////////////////////////////////////////////////////////// /// @brief The function that closes the port /// @description The function closes the port. //////////////////////////////////////////////////////////////////////////////// virtual void closePort() = 0; //////////////////////////////////////////////////////////////////////////////// /// @brief The function that clears the port /// @description The function clears the port. //////////////////////////////////////////////////////////////////////////////// virtual void clearPort() = 0; //////////////////////////////////////////////////////////////////////////////// /// @brief The function that sets port name into the port handler /// @description The function sets port name into the port handler. /// @param port_name Port name //////////////////////////////////////////////////////////////////////////////// virtual void setPortName(const char* port_name) = 0; //////////////////////////////////////////////////////////////////////////////// /// @brief The function that returns port name set into the port handler /// @description The function returns current port name set into the port handler. /// @return Port name //////////////////////////////////////////////////////////////////////////////// virtual char *getPortName() = 0; //////////////////////////////////////////////////////////////////////////////// /// @brief The function that sets baudrate into the port handler /// @description The function sets baudrate into the port handler. /// @param baudrate Baudrate /// @return false /// @return when error was occurred during port opening /// @return or true //////////////////////////////////////////////////////////////////////////////// virtual bool setBaudRate(const int baudrate) = 0; //////////////////////////////////////////////////////////////////////////////// /// @brief The function that returns current baudrate set into the port handler /// @description The function returns current baudrate set into the port handler. /// @return Baudrate //////////////////////////////////////////////////////////////////////////////// virtual int getBaudRate() = 0; //////////////////////////////////////////////////////////////////////////////// /// @brief The function that checks how much bytes are able to be read from the port buffer /// @description The function checks how much bytes are able to be read from the port buffer /// @description and returns the number. /// @return Length of read-able bytes in the port buffer //////////////////////////////////////////////////////////////////////////////// virtual int getBytesAvailable() = 0; //////////////////////////////////////////////////////////////////////////////// /// @brief The function that reads bytes from the port buffer /// @description The function gets bytes from the port buffer, /// @description and returns a number of bytes read. /// @param packet Buffer for the packet received /// @param length Length of the buffer for read /// @return -1 /// @return when error was occurred /// @return or Length of bytes read //////////////////////////////////////////////////////////////////////////////// virtual int readPort(uint8_t *packet, int length) = 0; //////////////////////////////////////////////////////////////////////////////// /// @brief The function that writes bytes on the port buffer /// @description The function writes bytes on the port buffer, /// @description and returns a number of bytes which are successfully written. /// @param packet Buffer which would be written on the port buffer /// @param length Length of the buffer for write /// @return -1 /// @return when error was occurred /// @return or Length of bytes written //////////////////////////////////////////////////////////////////////////////// virtual int writePort(uint8_t *packet, int length) = 0; //////////////////////////////////////////////////////////////////////////////// /// @brief The function that sets and starts stopwatch for watching packet timeout /// @description The function sets the stopwatch by getting current time and the time of packet timeout with packet_length. /// @param packet_length Length of the packet expected to be received //////////////////////////////////////////////////////////////////////////////// virtual void setPacketTimeout(uint16_t packet_length) = 0; //////////////////////////////////////////////////////////////////////////////// /// @brief The function that sets and starts stopwatch for watching packet timeout /// @description The function sets the stopwatch by getting current time and the time of packet timeout with msec. /// @param packet_length Length of the packet expected to be received //////////////////////////////////////////////////////////////////////////////// virtual void setPacketTimeout(double msec) = 0; //////////////////////////////////////////////////////////////////////////////// /// @brief The function that checks whether packet timeout is occurred /// @description The function checks whether current time is passed by the time of packet timeout from the time set by PortHandlerLinux::setPacketTimeout(). //////////////////////////////////////////////////////////////////////////////// virtual bool isPacketTimeout() = 0; }; } #endif /* DYNAMIXEL_SDK_INCLUDE_DYNAMIXEL_SDK_PORTHANDLER_H_ */
-
@Factao said in undefined reference to `__imp__ZN9dynamixel11PortHandler14getPortHandlerEPKc', which should stand for dynamixel::PortHandler :: getPortHandler(char const*):
I should, but it does not seem to help my case.
But not in your pro file you posted...
Did you compile the lib by yourself? If not - is it compiled with MinGW?
-
@Christian-Ehrlicher nice guess!
I just checked the .zip file, sure enough there's a .llib and a .dll in there, in DynamixelSDK-3.7.31\c++\build\win64, but a dead giveaway is that the directory contains a dxl_x64_cpp.sln file. Stringdumping the dxl_x64_cpp.lib, the output shows:
__imp_?getPortHandler@PortHandler@dynamixel@@SAPEAV12@PEBD@Z
which is Microsoft flavored name decoration (and the dxl_x64_cpp.dll has a dependency on VCRUNTIME140.dll :-(So to get a working app: either switch a MSVC compiler or rebuild the Dynamixel SDK using MinGW.
-
@hskoglund Thank you very much, I think there is some progress being made. After installing MVSC19 and using it's compilers in Qt, I now get the following error:
com.obj:-1: error: LNK2019: unresolved external symbol "__declspec(dllimport) public: static class dynamixel::PortHandler * __cdecl dynamixel::PortHandler::getPortHandler(char const *)" (__imp_?getPortHandler@PortHandler@dynamixel@@SAPEAV12@PEBD@Z) referenced in function "public: __cdecl com::com(char const *,int,class QObject *)" (??0com@@QEAA@PEBDHPEAVQObject@@@Z)
I do not understand where it is coming from. Do I need to do more than just switching to another compiler?
From what @Christian-Ehrlicher said, do I need to rebuild the library for MSVC too? I tried with MinGW, but the result where still the same.
-
Hi, you need to specify the path to that import library dxl_x64_cpp.lib in your .pro file, try:
LIBS += D:/Python/Library/Dynamixel_SDK/DynamixelSDK-3.7.31/c++/build/win64/output/dxl_x64_cpp.lib
and then to start your app successfully, you also need to copy the dxl_x64_cpp.dll file (it should be in the same directory as the .lib file above) to the same directory as your .exe file.
-
@hskoglund I tried specifying the path the way you proposed. I can now build correctly and both lines aren't instantly flagged, but rebuilding the whole project is still giving me the same issue.
I don't know if it's related, but while trying to run the programme, it crashes and tell me that dxl_x64_cpp.dll could not be found.I accidently put the dll file into the MinGW debug folder rather than in the MSVC folder. I can launch the app now.
It still give me the error mentioned in the title when I rebuild, but I no longer encounter any issue while building.
Thank you all!