неразрешенный внешний символ public __thiscall только в режиме отладки

0

Я просмотрел сообщения, пытающиеся решить эту ошибку, но в каждом случае я уже делаю то, что они предложили.

Мой результат компиляции:

main.obj: -1: ошибка: LNK2019: неразрешенный внешний символ "public: __thiscall KeyLogger :: ~ KeyLogger (void)" (?? 1KeyLogger @@QAE @XZ), на который ссылается функция _main

main.obj: -1: ошибка: LNK2019: неразрешенный внешний символ "public: __thiscall KeyLogger :: KeyLogger (void)" (? 0KeyLogger @@QAE @XZ), на который ссылается функция _main

debug\AccipioKeyDemo.exe: -1: ошибка: LNK1120: 2 нерешенных внешних

Я знаю, что это говорит о том, что у меня есть конструктор и деструктор KeyLogger, но не реализованы, но на самом деле у меня все реализовано.

main.cpp

#include <QCoreApplication>
#include "keylogger.h"

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    KeyLogger k;

    return a.exec();
}

keylogger.h

#ifndef KEYLOGGER_H
#define KEYLOGGER_H

#include <Windows.h>

class KeyLogger {

public:
    KeyLogger();
    ~KeyLogger();

    void start();
    void stop();

private:
    HHOOK hook;

    LRESULT CALLBACK intercept(int code, WPARAM wparam, LPARAM lparam);
};

#endif // KEYLOGGER_H

keylogger.cpp

#include "keylogger.h"
#include <QDebug>

KeyLogger::KeyLogger() : hook(NULL) {
    hook = SetWindowsHookEx(WH_KEYBOARD_LL, intercept, NULL,0);

    if (hook == NULL) {
        qDebug() << "HOOK FAILED";
    } else {
        qDebug() << "HOOK SUCCESS";
    }
}

KeyLogger::~KeyLogger() {

}

void KeyLogger::start() {
    qDebug() << "start";
}

void KeyLogger::stop() {
    qDebug() << "stop";
}

LRESULT CALLBACK KeyLogger::intercept(int code, WPARAM wparam, LPARAM lparam) {
    qDebug() << "Key Pressed";
    return CallNextHookEx(hook, code, wparam, lparam);
}

Конфигурация QT Pro

#-------------------------------------------------
#
# Project created by QtCreator 2013-10-10T19:58:51
#
#-------------------------------------------------

QT       += core

QT       -= gui

TARGET = AccipioKeyDemo
CONFIG   += console
CONFIG   -= app_bundle

LIBS += user32.lib

TEMPLATE = app

SOURCES += main.cpp \
    keylogger.cpp

HEADERS += \
    keylogger.h
Теги:
qt

2 ответа

2
Лучший ответ

Ваш код поврежден, потому что методы обратного вызова должны быть статическими членами - по существу, они должны быть свободными функциями. Так как нет способа передать указатель на экземпляр KeyLogger для перехвата функции обратного вызова, ваш крючок должен быть членом класса, а не членом экземпляра. Возможно, не такая уж плохая идея защитить крючок с помощью мьютекса, если вы позже забыли себя и попытались создать экземпляр KeyLogger в нескольких потоках.

Это также ошибка, в вашем случае, для того, чтобы объект KeyLogger мог быть скопирован. Используйте макрос Q_DISABLE_COPY для классов, которые не предназначены для копирования.

Возможно, вам захочется удалить каталог сборки и снова создать проект, но не забудьте исправить ошибки, как показано ниже, или это не сработает.

Минимальная версия ниже (только файл main.cpp) работает и компилируется просто отлично. Он демонстрирует, как правильно обрабатывать данные из очереди событий: вы должны скопировать небольшой фрагмент данных из очереди, удерживая мьютекс, затем отпустить мьютекс и только затем выгрузить его в другом месте.

#include <QCoreApplication>
#include <QMutex>
#include <QDebug>
#include <QQueue>
#include <QDataStream>
#include <windows.h>

struct KeyLoggerEvent {
   WPARAM event;
   KBDLLHOOKSTRUCT key;
   KeyLoggerEvent(WPARAM ev, KBDLLHOOKSTRUCT k) : event(ev), key(k) {}
};
QDataStream & operator<<(QDataStream & s, const KeyLoggerEvent & kev) {
   s << kev.event
     << (quint32)kev.key.flags << (quint32)kev.key.scanCode
     << (quint32)kev.key.time << (quint32)kev.key.vkCode;
   return s;
}

class KeyLogger {
   Q_DISABLE_COPY(KeyLogger)
   static QMutex m_hookMutex;
   static HHOOK m_hook;
   static QQueue<KeyLoggerEvent> m_events;
   static LRESULT CALLBACK intercept(int code, WPARAM wparam, LPARAM lparam);
public:
   KeyLogger() {
      QMutexLocker lock(&m_hookMutex);
      Q_ASSERT(!m_hook);
      m_hook = SetWindowsHookEx(WH_KEYBOARD_LL, intercept, NULL,0);
      if (!m_hook) qDebug() << "HOOK FAILED";
      lock.unlock();
   }
   ~KeyLogger() {
      QMutexLocker lock(&m_hookMutex);
      if (m_hook) UnhookWindowsHookEx(m_hook);
      m_hook = NULL;
   }
   //! Dumps a bunch of events to the stream. Returns false if no more events remain in the
   //! log. To avoid lock contention, it keeps the queue lock for a very short amount of time.
   bool dump(QDataStream & s) {
      int batchCount = 1000;
      QQueue<KeyLoggerEvent> dumpQueue;
      QMutexLocker lock(&m_hookMutex);
      while (batchCount-- && !m_events.empty()) {
         dumpQueue.enqueue(m_events.dequeue());
      }
      bool more = !m_events.empty();
      lock.unlock();
      // The below could block for a long time, thus it works from a local copy.
      while (! dumpQueue.empty()) s << dumpQueue.dequeue();
      return more;
   }
};

QMutex KeyLogger::m_hookMutex;
HHOOK KeyLogger::m_hook = NULL;
QQueue<KeyLoggerEvent> KeyLogger::m_events;

LRESULT CALLBACK KeyLogger::intercept(int code, WPARAM wparam, LPARAM lparam) {
   qDebug() << "Key Event";
   QMutexLocker lock(&m_hookMutex);
   if (code >= 0) {
      KBDLLHOOKSTRUCT * key = reinterpret_cast<KBDLLHOOKSTRUCT*>(lparam);
      m_events.enqueue(KeyLoggerEvent(wparam, *key));
   }
   HHOOK hook = KeyLogger::m_hook;
   lock.unlock();
   return CallNextHookEx(hook, code, wparam, lparam);
}

int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);
   KeyLogger k;
   return a.exec();
}
0

Вы получаете ошибку связи, где компоновщик не может найти файл obj с конструктором и деструктором. Это означает, что keylogger.cpp либо не скомпилирован, либо линкер не может найти свой obj файл. Проверьте настройки своего проекта.

  • 0
    Все файлы добавлены в проект, и мой вопрос был добавлен в вопрос
  • 0
    так, очевидно, я получаю эту ошибку только при компиляции в режиме отладки

Ещё вопросы

Сообщество Overcoder
Наверх
Меню