) I'm currently developing a project under Qt Creator 4.3.1 which needs an external library to use a key-lock hardware device.
The device comes with a CD with the libraries libkfunc64.so and libkfunc64.a (and the 32 bits versions) presumably compiled for C with gcc. I already tried the libraries in a dummy program to check if they work, and they do.
But when I add the important chunk of code into the Qt project it spits the following error
[...] error: undefined reference to `KFUNC(unsigned int, unsigned int, unsigned int, unsigned int)'
I've already tried to include the library
by coping the libraries to the system directories and simply including the following line in the .pro file
LIBS += -lkfunc64
by using relative paths to the libs in the .pro file
LIBS += -L$$PWD/../build-project/ -lkfunc64
INCLUDEPATH += $$PWD/../build-Qmetrics-Desktop-Debug
DEPENDPATH += $$PWD/../build-Qmetrics-Desktop-Debug
# PRE_TARGETDEPS += $$PWD/../build-Qmetrics-Desktop-Debug/libkfunc64.a
but it keeps showing this error when trying to (re)build it. I've read almost every subject about this issue on the internet but non of them fix this problem.
This is the code for main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QMessageBox>
// Key-lock stuff ----------
#define ValidateCode1 0X488B
#define ValidateCode2 0XFEE2
#define ValidateCode3 0XEF90
#define ClientIDCode1 0xB862
#define ClientIDCode2 0x54CB
#define ReadCode1 0X1772
#define ReadCode2 0XC4E6
#define ReadCode3 0XBCF8
extern unsigned long KFUNC(unsigned, unsigned, unsigned, unsigned);
unsigned RotateLeft(unsigned, int);
void KTASK(unsigned, unsigned, unsigned, unsigned);
unsigned short ReturnValue1, ReturnValue2;
// -------------------------
int main(int argc, char *argv[])
{
KTASK(1, ValidateCode1, ValidateCode2, ValidateCode3);
KTASK(RotateLeft(ReturnValue1, ReturnValue2 & 7) ^ ReadCode3 ^ ReturnValue2, RotateLeft(ReturnValue2, ReturnValue1 & 15), ReturnValue1 ^ ReturnValue2, 0);
if ((ReturnValue1 == ClientIDCode1) && (ReturnValue2 == ClientIDCode2))
{
QApplication app(argc, argv);
MainWindow w;
w.showFullScreen();
return app.exec();
}
else
{
QMessageBox msgBox;
msgBox.setText("Wrong or missing key-lock!");
return msgBox.exec();
}
}
unsigned RotateLeft(unsigned Target, int Counts)
{
int i;
static unsigned LocalTarget, HighBit;
LocalTarget = Target;
for (i=0; i<Counts; i++)
{
HighBit = LocalTarget & 0X8000;
LocalTarget = (LocalTarget << 1) + (HighBit >> 15);
}
LocalTarget = LocalTarget & 0XFFFF; /* For 32 bit integers */
return (LocalTarget);
}
void KTASK(unsigned CommandCode, unsigned Argument2, unsigned Argument3, unsigned Argument4)
{
unsigned long int ReturnValue;
ReturnValue = KFUNC(CommandCode, Argument2, Argument3, Argument4); // <--- this is the only function that is used from the external library
ReturnValue1 = (unsigned) (ReturnValue & 0XFFFF);
ReturnValue2 = (unsigned) (ReturnValue >> 16);
}
And the (relevant part of the) .pro file is as follow
# Adds OpenCV, DC1394 and Keylok libraries
unix {
CONFIG += link_pkgconfig
PKGCONFIG += opencv
LIBS += -ldc1394 -lkfunc64
}
I really don't know what to do :'(
Have you tried declaring the function with extern "C"?
e.G.:
#ifdef __cplusplus
extern "C"
{
#endif
extern unsigned long KFUNC(unsigned, unsigned, unsigned, unsigned);
#ifdef __cplusplus
};
#endif
This is nessecary to call a external c function from c++.
Related
I am trying to build this project, which is basically an extractor for specific .rom files. As someone with close to zero experience in coding, I am having one issue after another trying to build it.
The project description says it requires zlibstat.lib from zlib in order to build it, so I got the latest zlib, opened it on VS2019, followed these instructions, and built everything, included the required zlibstat.lib.
After opening the project's sln and figuring where to put the zlib related files, I tried to build but it gave me this error in fs.obj: "LNK2019: unresolved external symbol _uncompress referenced in function "int __cdecl run_extract(char *)" (?run_extract##YAHPAD#Z)". This is how far google and my two brain cells has led me to.
I am not exactly sure what I should do to solve this but apparently is has something to do with the run_extract function:
fs.h
#pragma once
#include <iostream>
#include <fstream>
#include "defs.h"
#include <zlib.h>
#pragma comment(lib, "zlibstat.lib")
#include <shlwapi.h>
#pragma comment(lib,"shlwapi.lib")
int run_extract(char *);
and fs.cpp
int run_extract(char *path)
{
std::fstream test;
test.open(path, std::ios::in | std::ios::binary);
if (!test) return -1;
size_t file_size;
test.seekg(0, std::ios::end);
file_size = test.tellg();
test.seekg(0, std::ios::beg);
unsigned char *buffer = new unsigned char [file_size];
test.read((char*)buffer, file_size);
test.close();
jrm_rom_header *ptrHeader = (jrm_rom_header*)buffer;
unsigned long indexLen = ptrHeader->count_index * sizeof(jrm_rom_file_index);
unsigned char *index = new unsigned char [indexLen];
uncompress(index, &indexLen, (const Bytef*)(buffer + ptrHeader->pos_index), ptrHeader->size_index); // use zlib
jrm_rom_file_index *ptrIndex = (jrm_rom_file_index*)index;
unsigned char key = 0;
char *path_out = new char[0x100];
unsigned long ypos = 0, x = 0;
for (x = 0; x<ptrHeader->count_index; x++)
{
key = (ptrIndex->key & 0xff) ^ (ptrIndex->key >> 8 & 0xff) ^ (ptrIndex->key >> 16 & 0xff) ^ (ptrIndex->key >> 24 & 0xff);
get_file_path(path_out, ptrIndex->file_path);
// printf("%04d: file_name = %s\n file_start = 0x%08x, file_size = 0x%08x, key = 0x%02x\n", x, path_out, ptrIndex->pos_start, ptrIndex->size_file, key);
printf("%s: %d bytes.\n", path_out, ptrIndex->size_file);
for (ypos = 0; ypos < ptrIndex->pos_delta; ypos++)
buffer[ypos + ptrIndex->pos_start] ^= key;
try_create_directory(path_out);
test.open(path_out, std::ios::binary | std::ios::out);
test.write((char*)buffer + ptrIndex->pos_start, ptrIndex->pos_delta);
test.close();
ptrIndex++;
}
delete[]path_out;
delete[]index;
delete[]buffer;
return 0;
}
I thought the problems would go away if I used the same Visual Studio version the project was made, so I installed the Visual C++ 2008 and an older version of zlib, only to end up having the exact same error.
Sorry if I am being dumb and having this entire situation poorly written.
EDIT: Added full MCV example project.
I have a strange problem where the same code and same input produce different output values.
The purpose of the code is to test a function that takes a value packed into 4 bytes, and unpack it into a single 32bit value. The expected value of value1, value2 and value3 in test_unpack() is 2018915346 (i.e. 0x78563412 because of little-endian unpacking). I got this method of unpacking from another answer. Below is an MCV example that you can easily build and see the problem for yourself. Note that if you comment out the body of test1() test_unpack() magically passes with the correct value.
test_canserialcomm.cpp
#include "test_canserialcomm.h"
#include <QtTest/QtTest>
#include <QByteArray>
long unpack() noexcept
{
quint8 a_bytes[] = {0x12, 0x34, 0x56, 0x78};
QByteArray a = QByteArray(reinterpret_cast<char*>(a_bytes), 4);
long value1 = *((long*)a.data());
qDebug() << value1; // outputs "32651099317351442" (incorrect value)
quint8 b_bytes[] = {0x12, 0x34, 0x56, 0x78};
QByteArray b = QByteArray(reinterpret_cast<char*>(b_bytes), 4);
long value2 = *((long*)b.data());
qDebug() << value2; // outputs "2018915346" (correct value)
quint8 c_bytes[] = {0x12, 0x34, 0x56, 0x78};
QByteArray c = QByteArray(reinterpret_cast<char*>(c_bytes), 4);
long value3 = *((long*)c.data());
qDebug() << value3; // outputs "2018915346" (correct value)
return value1;
}
void TestCanSerialComm::test1()
{
QCOMPARE("aoeu", "aoeu"); // If you comment this line, the next test will pass, as expected.
}
void TestCanSerialComm::test_unpack()
{
long expected {0x78563412};
QCOMPARE(unpack(), expected);
}
test_canserialcomm.h
#ifndef TEST_CANSERIALCOMM_H
#define TEST_CANSERIALCOMM_H
#include <QtTest>
class TestCanSerialComm: public QObject
{
Q_OBJECT
private slots:
void test1();
void test_unpack();
};
#endif // TEST_CANSERIALCOMM_H
test_main.cpp
#include <QtTest>
#include "test_canserialcomm.h"
#include <QCoreApplication>
int main(int argc, char** argv) {
QCoreApplication app(argc, argv);
TestCanSerialComm testCanSerialComm;
// Execute test-runner.
return QTest::qExec(&testCanSerialComm, argc, argv); }
tmp.pro
QT += core \
testlib
QT -= gui
CONFIG += c++11
TARGET = tmp
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
TARGET = UnitTests
HEADERS += test_canserialcomm.h
SOURCES += test_canserialcomm.cpp \
test_main.cpp
The output of value1 in test_unpack() is wrong, despite the same code and same inputs. Strangely, if I remove the qDebug() calls and set a breakpoint, the debugger expression evaluator now shows that value2 has the wrong value.
Any idea why this is happening? Or even how to troubleshoot this further?
Additional Notes: If I add a line qDebug() << "garbage"; at the top of my function, all 3 values produced are correct.
You're compiling and running this program on a system where long is 8 bytes, but your QByteArray has only 4 bytes. That means that when you alias the array as a long (using *((long*)a.data())) you're reading 4 bytes past the end of the array, into uninitialized heap storage.
The fix is to use a type that is guaranteed to be 4 bytes in size, e.g. std::int32_t.
As an aside, using *((long*)[...]) to alias memory is not guaranteed to work, primarily because of alignment issues but also (in the general case) because aliasing is only supported for types equivalent to char or a signed or unsigned variant. The safer technique is to use memcpy:
std::uint32_t value1;
assert(a.size() == sizeof(value1));
memcpy(&value1, a.data(), a.size());
I am trying to write a QT application that uses libXL, but when I try to compile, I get a pop up box saying "During Startup program exited with code 0xc0000135". I have figured out exactly which line causes the problem, it is the "Book* book = xlCreateBook();" line in startgame.cpp. When I comment this line out, the program runs fine. Is it possible that I set up the library incorrectly? I will try to include all relevant code below, and thanks in advance for any help!
stattracker.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = Stattracker
TEMPLATE = app
SOURCES += main.cpp\
stattracker.cpp \
startgame.cpp
HEADERS += stattracker.h \
varstruct.h \
startgame.h
FORMS += stattracker.ui
win32: LIBS += -L$$PWD/libxl-3.6.4.0/lib/libxl.lib
INCLUDEPATH += $$PWD/libxl-3.6.4.0/include_cpp
main.cpp
#include "stattracker.h"
#include <QApplication>
#include "varstruct.h"
#include <QString>
#include <windows.h>
#include <shlobj.h>
gameManager gm;
wchar_t homePath[MAX_PATH];
wchar_t awayPath[MAX_PATH];
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
gm = *new gameManager;
homePath[MAX_PATH] = *new wchar_t;
awayPath[MAX_PATH] = *new wchar_t;
Stattracker w;
w.show();
return a.exec();
}
startgame.cpp
#include ...
void Stattracker::initializeVars()
{
//This function initializes all game variables to starting value
}
void Stattracker::newFile(QString path, QString firstName, QString lastName)
{
using namespace libxl;
Book* book = xlCreateBook(); //WHEN THIS LINE IS COMMENTED, THE PROGRAM COMPILES FINE
}
void Stattracker::getInput()
{
bool homePosition[11], homeOrder[10], awayPosition[11], awayOrder[10];
wchar_t my_documents[MAX_PATH];
gm.homeTeam.teamName = ui->teamName->text();
gm.awayTeam.teamName = ui->teamName_2->text();
HRESULT result = SHGetFolderPath(NULL,CSIDL_PERSONAL,NULL,SHGFP_TYPE_CURRENT,my_documents);
QString documentsPath = QString::fromWCharArray(my_documents);
QString homePathA = documentsPath + "\\Stattracker\\" + gm.homeTeam.teamName;
QString awayPathA = documentsPath + "\\Stattracker\\" + gm.awayTeam.teamName;
QString pathCheckA = documentsPath + "\\Stattracker\\";
QString curFileA;
wchar_t pathCheckB[MAX_PATH];
wchar_t curFile[MAX_PATH];
pathCheckA.toWCharArray(pathCheckB);
homePathA.toWCharArray(homePath);
awayPathA.toWCharArray(awayPath);
if((GetFileAttributes(pathCheckB))==INVALID_FILE_ATTRIBUTES)
{
CreateDirectory(pathCheckB, 0);
}
if((GetFileAttributes(homePath))==INVALID_FILE_ATTRIBUTES)
{
CreateDirectory(homePath, 0);
}
if((GetFileAttributes(awayPath))==INVALID_FILE_ATTRIBUTES)
{
CreateDirectory(awayPath, 0);
}
if(ui->firstName->text()!="First Name" && ui->lastName->text()!="Last Name")
{
gm.homeTeam.roster[0].firstName = ui->firstName->text();
gm.homeTeam.roster[0].lastName = ui->lastName->text();
curFileA = homePathA + "\\" + gm.homeTeam.roster[0].lastName + "_" + gm.homeTeam.roster[0].firstName + ".xls";
curFileA.toWCharArray(curFile);
if((GetFileAttributes(curFile))==INVALID_FILE_ATTRIBUTES)
{
}
}
}
void Stattracker::startGame()
{
initializeVars();
getInput();
}
Let me know if I should include any of the other files (stattracker.cpp, stattracker.h, or varstruct.h)
Find libxl.dll and place it in the same directory as you .exe
I'm having trouble (dynamically) linking with the Qt libraries whilst compiling a C++ project with g++ 4.5.3:
g++ -Wall XMLInOut.cpp tinyxml2.cpp -I"C:\Qt\4.7.1\include" -I"$ADTF_ADDONS\adtf-device-toolbox\include" -L"C:\Qt\4.7.1\lib" -lQtCore4 -DtUInt32=uint -o xmltest.exe
The output is the following :
/tmp/cclJqe9S.o:XMLInOut.cpp:(.text+0x1db): undefined reference to `QString::toUInt(bool*, int) const'
/tmp/cclJqe9S.o:XMLInOut.cpp:(.text$_ZN7QStringC1EPKc[QString::QString(char const*)]+0x15): undefined reference to QString::fromAscii_helper(char const*, int)
/usr/lib/gcc/i686-pc-cygwin/4.5.3/../../../../i686-pc-cygwin/bin/ld: /tmp/cclJqe9S.o: bad reloc address 0x15 in section `.text$_ZN7QStringC1EPKc[QString::QString(char const*)]'
If I understand correctly, the -l option will link against a dynamic library. in the Qt/libs I have the QtCore4.dll
What am I doing wrong?
Cheers
EDIT :
Although I believe the problem lies fully in the linkage, I will post my code :
#include "XMLInOut.h"
#include "tinyxml2.h"
#include <iostream>
#include "ModelToInterfaceWrapper.h"
//#define __DEBUG_OUT_
#ifdef __DEBUG_OUT_
#define out(A) cout<<A
#else
#define out(A)
#endif
using namespace std;
using namespace tinyxml2;
void XMLInOut::readAndParseFile(const char* pFilename){
XMLDocument doc;
doc.LoadFile( "config.xml" );
XMLElement *service = doc.FirstChildElement( "root" )->FirstChildElement( "Service" );
for( service; service; service=service->NextSiblingElement() )
{// Iterating Services
out(endl<<service->FirstAttribute()->Value());
QString serviceName;
tUInt32 signalValue ;
const XMLAttribute* description = ((const XMLElement *)service)->FindAttribute("description");
if((const XMLAttribute*)0 != description){
out(" ("<<description->Value()<<")");
serviceName = description->Value();
}else {
serviceName = service->FirstAttribute()->Value();
}
for(XMLElement *signal = service->FirstChildElement( "Signal" ); signal; signal=signal->NextSiblingElement() ){
out(endl<<" "<<signal->GetText());
signalValue = (new QString (signal->GetText()))->toUInt();
}
}
}
int main(int argc, char **argv) {
XMLInOut xmlinOut;
xmlinOut.readAndParseFile("config.xml");
}
I am trying to write code for my atmega328 in C++ using Eclipse CDT. I have two projects. One project is static library project, that produces a static library. All the files in library are compiled without errors and library is created using the following command:
avr-ar -r "libRobotMainBoard.a" ./Console.o ./Motor.o ./RingBuffer.o ./io.o ./operators.o
c:\Program Files\WINAVR\bin\avr-ar.exe: creating libRobotMainBoard.a
Then I use this library in other project that produces hex file for my atmega. But during the linking I get error:
C:\Users\Mitch\Disk Google\workspace\AVR\RobotMainBoard\Release\libRobotMainBoard.a(Console.o): In function Console::putCharToUDR()':
Console.cpp:(.text._ZN7Console12putCharToUDREv+0x2): undefined reference to Console::txBuff'
and many othert similar to this. I have tried to find the solution on the web. Most of them mentions that this error is caused by naming library and the compiled file in the wrong order. I checked that and my order should be fine. I am linking it with the command:
avr-g++ -Wl,-Map,BoardTest.map,--cref -mrelax -Wl,--gc-sections -L"C:\Users\Mitch\Disk Google\workspace\AVR\RobotMainBoard\Release" -mmcu=atmega328p -o "BoardTest.elf" ./main.o -lRobotMainBoard
The main.cpp file looks like this:
#include <util/delay.h>
#include "Console.h"
#include "Motor.h"
Motor leftMotor(9,7);
Motor rightMotor(10,8);
int main(){
leftMotor.stop();
rightMotor.stop();
Console::setup(250000);
while(1){
Console::send('a');
_delay_ms(2000);
}
}
When I comment the Console lines out, it will link OK, even with Motor lines, which source files are in the same lib.
The Console cpp file is like this:
#include <avr/interrupt.h>
#include "Console.h"
#include "operators.h"
void Console::setup(uint16_t baudrate) {
rxBuff = new RingBuffer(RX_BUFF_SIZE);
txBuff = new RingBuffer(TX_BUFF_SIZE);
uint16_t baudPrescaler= (F_CPU / (baudrate * 16)) - 1;
UCSR0A = 0x00; UCSR0B = 0x00; UCSR0C = 0x00;
//Using 8-bit, asynchronous, normal speed, 1 stop bit, no parity check
UBRR0 = baudPrescaler;
UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00); //8-bit
UCSR0B |= (1 << TXEN0) | (1 << RXEN0);
sei();
}
void Console::send(char c) {
txBuff->add(c);
UCSR0B |= (1 << UDRIE0);
}
void Console::send(const char* s) {
while(*s){
send(*s++);
}
}
void Console::putCharToUDR(){
if(!txBuff->empty()){
UDR0 = txBuff->remove();
} else {
UCSR0B &= ~(1 << UDRIE0);
}
}
uint8_t Console::canReceive() {
return rxBuff->available();
}
uint8_t Console::canTransmit() {
return txBuff->available();
}
ISR(USART_RX_vect, ISR_BLOCK){
}
ISR(USART_UDRE_vect, ISR_BLOCK){
Console::putCharToUDR();
}
Do anybody of you have any idea, why I am still getting the linking error?
EDIT 1
#ifndef CONSOLE_H_
#define CONSOLE_H_
#include "RingBuffer.h"
#define RX_BUFF_SIZE 32
#define TX_BUFF_SIZE 32
class Console {
public:
static void setup(uint16_t baudrate);
static void send(char c);
static void send(const char* s);
static uint8_t canReceive();
static uint8_t canTransmit();
static void putCharToUDR();
private:
static RingBuffer *rxBuff;
static RingBuffer *txBuff;
};
#endif /* CONSOLE_H_ */
As txBuff is static, you have to provide its definition in Console.cpp, e.g.
RingBuffer * Console::txBuff = new RingBuffer(RX_BUFF_SIZE);