0

I get a bus error whenever I run this Python CGEventTap code:

def callback(ent):
    loc = CGEventGetLocation(ent)
    print loc

tap = CGEventTapCreate(
    kCGSessionEventTap,
    kCGHeadInsertEventTap, 
    kCGEventTapOptionDefault,
    CGEventMaskBit(kCGEventMouseMoved),
    callback(CGEventRef) )

loop = CFMachPortCreateRunLoopSource(None, tap, 0)
CFRunLoopAddSource(CFRunLoopGetCurrent(), loop, kCFRunLoopCommonModes)

RunApplicationEventLoop()

Is there something obvious that I'm missing?

Max
  • 4,529
  • 1
  • 25
  • 29
  • Are you _linking_ against the ApplicationServices framework (i.e., not just `import`ing it)? – jscs Mar 19 '11 at 03:39
  • 1
    @josh I have tried all of the following: import objc, from Foundation import *, from PyObjCTools import AppHelper, from Quartz import *, from AppKit import *. Which of these do I need and not need? And what do you mean by _linking_? – Max Mar 20 '11 at 22:59
  • An **important** note is that your callback needs to return `ent`, otherwise your program won't forward the input events to the next handlers and you'll lock your system up! – notbad.jpeg Dec 06 '16 at 23:16

1 Answers1

1

I have tried all of the following:... Which of these do I need and not need? And what do you mean by linking? – Teak

Replying to your comment with an answer because it won't fit in a comment. Sorry.

The situation is perhaps a little convoluted. PyObjC has a whole bunch of information (metadata and some helper code) about the functions, objects, etc. in Apple's frameworks, but it doesn't contain the code itself (because it's Apple's code, and PyObjC can't just go around copying it). The functions you're using are in Apple's ApplicationServices framework. PyObjC keeps its information about that framework in its Quartz module. So Part I is: to use these functions in Python, you need to get PyObjC's info: from Quartz import *.

Part II is that, like I said, your application here needs to know, not just where PyObjC's metadata is, but where Apple's code that you're trying to use is. This is the linking part. (It doesn't look like you're using Xcode, since you're setting up your own run loop, but in Xcode, you would go to the Linked Frameworks group in your project and add ApplicationServices to it.)

I guess you're using py2app? I'm afraid I'm not 100% sure how to do it that way, but this SO question might get you started: Problem using py2app

Hope that points you in a helpful direction.

(By the way, when I set up a project with your code, in Xcode and with the ApplicationServices framework linked in, it locked up my input devices so that the only thing I could do was reboot. I may have done something wrong, but be warned that when you get this linked, there may be other problems with the tap you're setting up. You might possibly want to try doing this in C/Obj-C first and then translating into Python when you know it works.)

Community
  • 1
  • 1
jscs
  • 63,694
  • 13
  • 151
  • 195
  • Thank you. That's very helpful, as is the thread you pointed me to. I will try some of your suggestions. And thanks for the warning... – Max Mar 21 '11 at 18:23
  • Glad I could help. I noticed from your question history that you've been working on this puzzle for quite a while. Good luck! – jscs Mar 21 '11 at 21:17
  • @Teak: Just saw a mention of this utility: http://pfiddlesoft.com/eventtapstestbench/ in a cocoa-dev mailing list thread. Haven't tried it, but it might be useful to you. – jscs Mar 22 '11 at 02:08
  • @Josh: I have been working on this awhile. Is it possible for you to some how send me the Xcode project you made, or just the code, as I'm a Python person and have little understanding of C and Xcode? Also I already have Event Taps Testbench, (found it during my extensive and unsuccessful research) thanks though. – Max Mar 23 '11 at 18:41
  • @Teak: sorry, when I tried it out in Xcode (so that I could be sure it was linked) I was also using Python. I never bothered to try it in C after having to reboot. The reason I suggested using C is that I've found that PyObjC seems to have the roughest edges around the plain-C Apple APIs (as opposed to the ones written in Objective-C). If you don't have much C practice, I guess just ignore that idea. Sorry. You can make an Xcode PyObjC project pretty easily yourself, though, and run the code you have in that. – jscs Mar 24 '11 at 00:14
  • @Josh: Okay, so when I put the code into Xcode and run it, it does what you said and my system freezes. But when I run the same script from the Xcode project in a terminal window, (using command: python ) it returns: Bus Error. So I don't know what to try next... – Max Mar 24 '11 at 20:13
  • @Teak: Hmm, I'm afraid I don't know either. I was getting SEG_FAULTs when I did it on the command line. I'd guess that Python is passing some object back to the C side, and the memory for that object isn't being handled correctly, but I haven't got the foggiest what that could be. Maybe post a brief question on the [PyObjC mailing list](http://sourceforge.net/mail/?group_id=14534)? Ronald Oussoren, the main developer, seems to be a nice enough fellow. This might be an opportunity for you to teach yourself C! :) – jscs Mar 25 '11 at 06:06