Python和C交互回调函数

Python和C交互回调函数,python,c,Python,C,我正在为我的一个研究项目制作一个MacOS键盘记录器。 我有一个C代码,可以抓取击键并将其写入文本文件。(下面的代码我拿出了一些不重要的东西) 我现在需要做的就像PyHook一样,而不是将数据写入文本文件, 将Python回调函数传递给C代码并使其将键输入传回Python,这样我就可以使用Python进行必要的分析 我一直在寻找如何做到这一点,但老实说,我不知道如何做到这一点,因为我不习惯C编程或Python扩展。任何帮助都将不胜感激 #include <Carbon/Carbon.h&g

我正在为我的一个研究项目制作一个MacOS键盘记录器。 我有一个C代码,可以抓取击键并将其写入文本文件。(下面的代码我拿出了一些不重要的东西)

我现在需要做的就像PyHook一样,而不是将数据写入文本文件, 将Python回调函数传递给C代码并使其将键输入传回Python,这样我就可以使用Python进行必要的分析

我一直在寻找如何做到这一点,但老实说,我不知道如何做到这一点,因为我不习惯C编程或Python扩展。任何帮助都将不胜感激

#include <Carbon/Carbon.h>
#include <ApplicationServices/ApplicationServices.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/time.h>

#define NUM_RECORDING_EVENT_TYPES 5
#define RECORD 0
#define MOUSEACTION 0
#define KEYSTROKE 1
// maximum expected line length, for fgets
#define LINE_LENGTH 80
#define kShowMouse TRUE

OSStatus RUIRecordingEventOccurred(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData);

void prepareToRecord(); // install the event handler, wait for record signal

// note that keyboard character codes are found in Figure C2 of the document
// Inside Macintosh: Text available from http://developer.apple.com
char * keyStringForKeyCode(int keyCode); // get the representation of the Mac keycode

// Global Variables
int dieNow = 0;    // should the program terminate
int ifexit = 0;       // Exit state 
char *filename = NULL;  // Log file name
FILE *fd = NULL;   // Log file descriptor

int typecount = 0;          // count keystroke to periodically save to a txt file

struct timeval thetime;  // for gettimeofday
long currenttime;   // the current time in milliseconds

int main()
{
    filename = "test.txt";
    fd = fopen(filename, "a");

    // Get RUI ready to record or play, based off of mode
    prepareToRecord();

 return EXIT_SUCCESS;
}

// event handler for RUI recorder
OSStatus RUIRecordingEventOccurred(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData)
{
 // Determine class and kind of event
    int eventClass = GetEventClass(theEvent);
    int eventKind = GetEventKind(theEvent);

    /* Handle Keyboard Events */
    if((eventClass == kEventClassKeyboard) && (eventKind == kEventRawKeyDown)) /* key release implied */ {
        int keyCode, modifiers;  // what did the user press? any modifier keys down?

  // gather keystroke information
        GetEventParameter(theEvent, kEventParamKeyCode, typeInteger, NULL, sizeof(keyCode), NULL, &keyCode);
        GetEventParameter(theEvent, kEventParamKeyModifiers, typeInteger, NULL, sizeof(modifiers), NULL, &modifiers);

        // What time is it?
        gettimeofday(&thetime, NULL);
        currenttime =(((thetime.tv_sec*1000000) + (thetime.tv_usec)));

  fprintf(fd, "%s\n", keyStringForKeyCode(keyCode));

    } 

    return EXIT_SUCCESS;
}


void prepareToRecord()
{
 EventRecord event;  // holds an event for examination

    // Types of events to listen for
    EventTypeSpec eventTypes[NUM_RECORDING_EVENT_TYPES] = {{kEventClassKeyboard, kEventRawKeyDown}};

 // Install the event handler
    InstallEventHandler(GetEventMonitorTarget(), NewEventHandlerUPP(RUIRecordingEventOccurred), NUM_RECORDING_EVENT_TYPES, eventTypes, nil, nil);

    // event loop - get events until die command
 do {
        WaitNextEvent((everyEvent),&event,GetCaretTime(),nil);
 } while (dieNow == 0);
}


char * keyStringForKeyCode(int keyCode)
{
 // return key char
 switch (keyCode) {
  case 0: return("a");
 default: return("Empty"); // Unknown key, Return "Empty"
 }
}
#包括
#包括
#包括
#包括
#包括
#定义数字记录事件类型5
#定义记录0
#定义鼠标动作0
#定义击键1
//FGET的最大预期线长度
#定义线的长度为80
#定义kShowMouse TRUE
OSStatus RUI记录发生的事件(EventHandlerCallRef nextHandler、EventRef theEvent、void*用户数据);
void prepareToRecord();//安装事件处理程序,等待记录信号
//注意,在文档的图C2中可以找到键盘字符代码
//Macintosh内部:文本可从http://developer.apple.com
char*keystringworkeycode(int-keyCode);//获取Mac密钥码的表示形式
//全局变量
int dieNow=0;//程序应该终止吗
int ifexit=0;//退出状态
char*filename=NULL;//日志文件名
文件*fd=NULL;//日志文件描述符
int typecount=0;//计数击键次数以定期保存到txt文件
struct timeval thetime;//暂时
长当前时间;//当前时间(以毫秒为单位)
int main()
{
filename=“test.txt”;
fd=fopen(文件名,“a”);
//准备好录制或播放,以关闭模式为基础
准备记录();
返回退出成功;
}
//RUI记录器的事件处理程序
OSStatus RUI记录事件发生(EventHandlerCallRef nextHandler、EventRef theEvent、void*用户数据)
{
//确定事件的类别和种类
int eventClass=GetEventClass(theEvent);
int eventKind=GetEventKind(theEvent);
/*处理键盘事件*/
if((eventClass==kEventClassKeyboard)&&(eventKind==kEventRawKeyDown))/*暗含按键释放*/{
int keyCode,modifiers;//用户按了什么键?是否有任何修改键被按下?
//收集击键信息
GetEventParameter(theEvent、kEventParamKeyCode、typeInteger、NULL、sizeof(keyCode)、NULL和keyCode);
GetEventParameter(theEvent、kEventParamKeyModifiers、typeInteger、NULL、sizeof(修饰符)、NULL和修饰符);
//现在几点了?
gettimeofday(&thetime,NULL);
currenttime=((time.tv_sec*1000000)+(time.tv_usec));
fprintf(fd,“%s\n”,keystringworkeycode(keyCode));
} 
返回退出成功;
}
无效记录()
{
EventRecord event;//保存一个事件以供检查
//要侦听的事件类型
EventTypeSpec eventTypes[NUM_RECORDING_EVENT_TYPES]={{{kEventClassKeyboard,kEventRawKeyDown}};
//安装事件处理程序
InstallEventHandler(GetEventMonitorTarget()、NewEventHandlerUPP(RuiRecordingEventOccurse)、NUM\u RECORDING\u EVENT\u TYPES、eventTypes、nil、nil);
//事件循环-获取事件直到死亡命令
做{
WaitNextEvent((everyEvent),&event,GetCaretTime(),nil);
}而(dieNow==0);
}
char*keystringworkeycode(int-keyCode)
{
//返回键字符
开关(钥匙代码){
案例0:返回(“a”);
默认值:return(“Empty”);//未知键,返回“Empty”
}
}

很简单-只需按照说明操作即可


或者,如果您试图从Python调用C/C++函数,您可以使用或Python的模块之一

谢谢!似乎我可以使用SWIG将C代码编译成.so文件,然后在Python中与CTypes一起使用,如果我理解正确的话。希望我能弄明白@joon的教程非常全面,并附有代码示例。你应该不会有什么麻烦。祝你一切顺利……非常感谢。我真的很感激。而且,要遵守SO的传统。请对答案进行投票,并将对您最有帮助的答案标记为您问题的“正确”答案。这有助于论坛和用户。