未解析的外部符号public __thiscall仅在调试模式下

时间:2013-10-11 02:16:50

标签: c++ qt

我已经四处寻找试图解决此错误的帖子但是在每种情况下我都在做他们建议的事情。

我的编译输出:

  

main.obj:-1:错误:LNK2019:未解析的外部符号“public:   __thiscall KeyLogger :: ~KeyLogger(void)“(?? 1KeyLogger @@ QAE @ XZ)在函数_main中引用

     

main.obj:-1:错误:LNK2019:未解析的外部符号“public:   函数_main

中引用__thiscall KeyLogger :: KeyLogger(void)“(?? 0KeyLogger @@ QAE @ XZ)      

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

2 个答案:

答案 0 :(得分: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();
}

答案 1 :(得分:0)

您收到链接错误,链接器无法找到带构造函数和析构函数的obj文件。这意味着keylogger.cpp要么没有编译,要么链接器找不到它的obj文件。检查项目的设置。