Thread: Re: [Pyobjc-dev] NSDocument based app
Brought to you by:
ronaldoussoren
From: Peter M. <zig...@po...> - 2002-11-06 07:54:15
|
The app works correctly in all the cases you mentioned. It will also correctly open a new window when it is brought to the front by clicking on the dock icon, if no other documents are open. Like I said, everything else I've tried works. Except printing. How do selectors work? Specifically I need to call runModalPageLayoutWithPrintInfo:delegate:didRunSelector:contextInfo: How do I pass a selector to this? I actually want to send a NULL for the selector (I have nothing to do when the sheet is closed). In ObjC I'd do something like: [self runModalPrintOperation:op delegate:nil didRunSelector:NULL contextInfo:NULL]; If you can't do a NULL selector in PyObjC, I'd settle for knowing how to specify a valid selector :-) Thanks, Peter On Wednesday, November 6, 2002, at 05:05 PM, bb...@ma... wrote: > Cool! This sounds like an excellent example to (a) include in the > Examples/ directory and (b) model the Multi-Document project template > after! > > In terms of the bug: Does the app work correctly when you drag-n-drop > a file onto the dock icon to open the document? I recently put > together a multi-doc architecture app and everything works perfectly > but that-- I didn't notice the lack of an untitled doc on launch > because I implemented the method that *should* disable it from the > start (but never checked that the method was actually invoked). > > b.bum |
From: Ronald O. <ous...@ci...> - 2002-11-06 08:28:27
|
On Wednesday, Nov 6, 2002, at 08:53 Europe/Amsterdam, Peter Montagner wrote: > The app works correctly in all the cases you mentioned. It will also > correctly open a new window when it is brought to the front by > clicking on the dock icon, if no other documents are open. Like I > said, everything else I've tried works. The Todo application that is part of the source-tree has the same problem. That's not very helpfull, but at least this shows the problem is probably in PyObjC. > > Except printing. How do selectors work? Specifically I need to call > > runModalPageLayoutWithPrintInfo:delegate:didRunSelector:contextInfo: > > How do I pass a selector to this? I actually want to send a NULL for > the selector (I have nothing to do when the sheet is closed). In ObjC > I'd do something like: > > [self runModalPrintOperation:op > delegate:nil > didRunSelector:NULL > contextInfo:NULL]; Selectors (type SEL in Objective-C) are represented as strings in Python: self.runModalPrintOperation_delagate_didRunSelector_contextInfo_( op, nil, "mySelector:", None) |
From: Peter M. <zig...@po...> - 2002-11-06 09:21:22
|
On Wednesday, November 6, 2002, at 07:28 PM, Ronald Oussoren wrote: > > On Wednesday, Nov 6, 2002, at 08:53 Europe/Amsterdam, Peter Montagner =20= > wrote: > >> The app works correctly in all the cases you mentioned. It will also =20= >> correctly open a new window when it is brought to the front by =20 >> clicking on the dock icon, if no other documents are open. Like I =20 >> said, everything else I've tried works. > The Todo application that is part of the source-tree has the same =20 > problem. That's not very helpfull, but at least this shows the problem = =20 > is probably in PyObjC. Good to hear. No wait, that's bad. Any idea what's causing it? >> Except printing. How do selectors work? Specifically I need to call >> >> runModalPageLayoutWithPrintInfo:delegate:didRunSelector:contextInfo: >> >> How do I pass a selector to this? I actually want to send a NULL for =20= >> the selector (I have nothing to do when the sheet is closed). In ObjC = =20 >> I'd do something like: >> >> [self runModalPrintOperation:op >> delegate:nil >> didRunSelector:NULL >> contextInfo:NULL]; > Selectors (type SEL in Objective-C) are represented as strings in =20 > Python: > > self.runModalPrintOperation_delagate_didRunSelector_contextInfo_( > op, nil, "mySelector:", None) For some unknown reason, that isn't working. It dies while executing - (void)runModalPrintOperation:(NSPrintOperation *)printOperation =20 delegate:(id)delegate didRunSelector:(SEL)didRunSelector =20 contextInfo:(void *)contextInfo Here the method: # Print our document def printShowingPrintPanel_(self, showPanels): printInfo =3D self.printInfo() printOp =3D =20 NSPrintOperation.printOperationWithView_printInfo_(self.rtfTextView,prin=20= tInfo) printOp.setShowPanels_(showPanels) =20 self.runModalPrintOperation_delegate_didRunSelector_contextInfo_( printOp, self, "printOperationDidRun:success:contextInfo:", = =20 None) It gets this error: objc_sizeof_type: Unhandled type '=00' I'm probably doing something stupid. Peter= |
From: Ronald O. <ous...@ci...> - 2002-11-06 09:34:47
|
On Wednesday, Nov 6, 2002, at 10:21 Europe/Amsterdam, Peter Montagner wrote: > > On Wednesday, November 6, 2002, at 07:28 PM, Ronald Oussoren wrote: > >> >> On Wednesday, Nov 6, 2002, at 08:53 Europe/Amsterdam, Peter Montagner >> wrote: >> >>> The app works correctly in all the cases you mentioned. It will also >>> correctly open a new window when it is brought to the front by >>> clicking on the dock icon, if no other documents are open. Like I >>> said, everything else I've tried works. >> The Todo application that is part of the source-tree has the same >> problem. That's not very helpfull, but at least this shows the >> problem is probably in PyObjC. > > Good to hear. No wait, that's bad. Any idea what's causing it? Not yet... > > >>> Except printing. How do selectors work? Specifically I need to call >>> >>> runModalPageLayoutWithPrintInfo:delegate:didRunSelector:contextInfo: >>> >>> How do I pass a selector to this? I actually want to send a NULL for >>> the selector (I have nothing to do when the sheet is closed). In >>> ObjC I'd do something like: >>> >>> [self runModalPrintOperation:op >>> delegate:nil >>> didRunSelector:NULL >>> contextInfo:NULL]; >> Selectors (type SEL in Objective-C) are represented as strings in >> Python: >> >> self.runModalPrintOperation_delagate_didRunSelector_contextInfo_( >> op, nil, "mySelector:", None) > > For some unknown reason, that isn't working. It dies while executing > > - (void)runModalPrintOperation:(NSPrintOperation *)printOperation > delegate:(id)delegate didRunSelector:(SEL)didRunSelector > contextInfo:(void *)contextInfo The last argument is problematic: void pointers currently require manual assistance. We can at least support automatic translation from None to a NULL pointer. The error message is not very helpfull. Ronald |
From: Peter M. <zig...@po...> - 2002-11-06 09:52:22
|
On Wednesday, November 6, 2002, at 08:34 PM, Ronald Oussoren wrote: > > On Wednesday, Nov 6, 2002, at 10:21 Europe/Amsterdam, Peter Montagner > wrote: > >> >> On Wednesday, November 6, 2002, at 07:28 PM, Ronald Oussoren wrote: >> >>> >>> On Wednesday, Nov 6, 2002, at 08:53 Europe/Amsterdam, Peter >>> Montagner wrote: >>> >>>> The app works correctly in all the cases you mentioned. It will >>>> also correctly open a new window when it is brought to the front by >>>> clicking on the dock icon, if no other documents are open. Like I >>>> said, everything else I've tried works. >>> The Todo application that is part of the source-tree has the same >>> problem. That's not very helpfull, but at least this shows the >>> problem is probably in PyObjC. >> >> Good to hear. No wait, that's bad. Any idea what's causing it? > Not yet... I'll take a look. I'm pretty new to PyObjC, but I've been programming in Objective-C since the Mac OS X PB came out. >> For some unknown reason, that isn't working. It dies while executing >> >> - (void)runModalPrintOperation:(NSPrintOperation *)printOperation >> delegate:(id)delegate didRunSelector:(SEL)didRunSelector >> contextInfo:(void *)contextInfo > > The last argument is problematic: void pointers currently require > manual assistance. We can at least support automatic translation from > None to a NULL pointer. So (void *) arguments are broken? Hmm... well I can avoid that in my example app by using the print panel rather than the sheet. The panel doesn't require a call back. There are a few things that use the (void *)contextInfo paradigm though, so we should probably fix it. What's the current scheme? Peter |
From: Ronald O. <ous...@ci...> - 2002-11-06 10:19:20
|
On Wednesday, Nov 6, 2002, at 10:52 Europe/Amsterdam, Peter Montagner wrote: >> The last argument is problematic: void pointers currently require >> manual assistance. We can at least support automatic translation from >> None to a NULL pointer. > > So (void *) arguments are broken? Hmm... well I can avoid that in my > example app by using the print panel rather than the sheet. The panel > doesn't require a call back. There are a few things that use the (void > *)contextInfo paradigm though, so we should probably fix it. What's > the current scheme? > Not really broken, just not working as you want :-) Problem is that it hard to automaticly translate from a Python object to a void*: Do you want to pass the object itself (like you probably want to do here) or should the object be translated to some native type (like you'd want to do with 'int write(int fd, void* buf, int len)'). The current scheme is that you'll have to manually write methods that do the right thing. But, I'll probably add a mechanism to get this type of void* arguments to work without writing C code. Ronald |
From: Peter M. <zig...@po...> - 2002-11-06 10:53:13
|
On Wednesday, November 6, 2002, at 09:19 PM, Ronald Oussoren wrote: > > On Wednesday, Nov 6, 2002, at 10:52 Europe/Amsterdam, Peter Montagner > wrote: >>> The last argument is problematic: void pointers currently require >>> manual assistance. We can at least support automatic translation >>> from None to a NULL pointer. >> >> So (void *) arguments are broken? Hmm... well I can avoid that in my >> example app by using the print panel rather than the sheet. The panel >> doesn't require a call back. There are a few things that use the >> (void *)contextInfo paradigm though, so we should probably fix it. >> What's the current scheme? >> > Not really broken, just not working as you want :-) Problem is that it > hard to automaticly translate from a Python object to a void*: Do you > want to pass the object itself (like you probably want to do here) or > should the object be translated to some native type (like you'd want > to do with 'int write(int fd, void* buf, int len)'). > > The current scheme is that you'll have to manually write methods that > do the right thing. But, I'll probably add a mechanism to get this > type of void* arguments to work without writing C code. Doing a quick grep of the AppKit.framework headers reveals that there are about 40 methods with a (void *) argument and a few that return a (void *). Almost all of those that use (void *) as an argument use it in the same way as my method, as an extra bit of user data. Even if nobody uses it, PyObjC will still choke on all of those methods. If I understand this correctly of course. The Foundation.framework has about 20 but most of those aren't the kind of thing you'd call from Python. Peter |
From: Jack J. <Jac...@cw...> - 2002-11-06 11:26:14
|
On Wednesday, Nov 6, 2002, at 11:19 Europe/Amsterdam, Ronald Oussoren wrote: >> So (void *) arguments are broken? Hmm... well I can avoid that in my >> example app by using the print panel rather than the sheet. The panel >> doesn't require a call back. There are a few things that use the >> (void *)contextInfo paradigm though, so we should probably fix it. >> What's the current scheme? >> > Not really broken, just not working as you want :-) Problem is that it > hard to automaticly translate from a Python object to a void*: Do you > want to pass the object itself (like you probably want to do here) or > should the object be translated to some native type (like you'd want > to do with 'int write(int fd, void* buf, int len)'). > > The current scheme is that you'll have to manually write methods that > do the right thing. But, I'll probably add a mechanism to get this > type of void* arguments to work without writing C code. What I tend to do if I run into this situation when wrapping an API is the following: - If the Python object is None I pass NULL, else - If the Python object conforms to the buffer protocol we use bf_getreadbuffer() or bf_getwritebuffer(), else - if it's a PyCObject we use PyCObject_AsVoidPtr(). -- - Jack Jansen <Jac...@or...> http://www.cwi.nl/~jack - - If I can't dance I don't want to be part of your revolution -- Emma Goldman - |
From: <bb...@ma...> - 2002-11-07 16:15:05
|
That seems like about as close to a workable set of behaviors as we can get without special casing certain methods. For contexts that use a (void *) as a bit of userInfo, we simply need to make sure that a Python object passed in can be recovered during the call back. This will likely require a treat-that-void-thing-as-a-python-object-reference and also raises the what-if-it-should-really-be-an-NSObject specter. b.bum On Wednesday, November 6, 2002, at 06:26 AM, Jack Jansen wrote: > What I tend to do if I run into this situation when wrapping an API is > the following: > - If the Python object is None I pass NULL, else > - If the Python object conforms to the buffer protocol we use > bf_getreadbuffer() or bf_getwritebuffer(), else > - if it's a PyCObject we use PyCObject_AsVoidPtr(). |
From: Ronald O. <ous...@ci...> - 2002-11-08 06:41:43
|
On Thursday, Nov 7, 2002, at 17:12 Europe/Amsterdam, bb...@ma... wrote: > That seems like about as close to a workable set of behaviors as we > can get without special casing certain methods. For contexts that > use a (void *) as a bit of userInfo, we simply need to make sure that > a Python object passed in can be recovered during the call back. I thought of an simpler way to "fix" this on the way home last night. PyObjC has a mechanism to change the signatures of Objective-C methods as seen from Python. We could use this to change all '(void*)userInfo' arguments to '(int)userInfo' arguments. At the very least this allows us to actually use these methods until we come up with a better solution. If the userInfo will always be passed back to Python code this is solution is good enough for me: Even if you wanted to pass a python object you could stuff that Python object into a list and pass the list index to the selector. This obviously is not the right fix in general (what if you want to use an existing method that expects a pointer to some data). Ronald |
From: Peter M. <zig...@po...> - 2002-11-08 10:00:02
|
On Friday, November 8, 2002, at 05:41 PM, Ronald Oussoren wrote: > > On Thursday, Nov 7, 2002, at 17:12 Europe/Amsterdam, bb...@ma... > wrote: > >> That seems like about as close to a workable set of behaviors as we >> can get without special casing certain methods. For contexts that >> use a (void *) as a bit of userInfo, we simply need to make sure that >> a Python object passed in can be recovered during the call back. > I thought of an simpler way to "fix" this on the way home last night. > PyObjC has a mechanism to change the signatures of Objective-C methods > as seen from Python. We could use this to change all '(void*)userInfo' > arguments to '(int)userInfo' arguments. At the very least this allows > us to actually use these methods until we come up with a better > solution. If the userInfo will always be passed back to Python code > this is solution is good enough for me: Even if you wanted to pass a > python object you could stuff that Python object into a list and pass > the list index to the selector. > > This obviously is not the right fix in general (what if you want to > use an existing method that expects a pointer to some data). So you think that we should treat (void*) as an integer rather than a pointer, right? That works for me but it does seem a bit inelegant. Is there anything in python (2.2 onwards of course) that isn't an object? If not, I think we should consider (void *) to be synonymous with (id). The other use for (void*), as a pointer to block of memory (eg. write()), can't really be done in python without wrapping it in an object, right? So any API using (void *) for that purpose would need to be specially wrapped anyway. Am I wrong? Peter |
From: Ronald O. <ous...@ci...> - 2002-11-08 10:31:49
|
On Friday, Nov 8, 2002, at 10:59 Europe/Amsterdam, Peter Montagner wrote: > So you think that we should treat (void*) as an integer rather than a > pointer, right? That works for me but it does seem a bit inelegant. At least for now and only for specific methods. It is not very elegant, but at least it allows you to use a number of APIs that are off-limits at the moment. BTW. I did not propose to treat all void* as integers, that would make it impossible to use some other APIs. > > Is there anything in python (2.2 onwards of course) that isn't an > object? If not, I think we should consider (void *) to be synonymous > with (id). The other use for (void*), as a pointer to block of memory > (eg. write()), can't really be done in python without wrapping it in > an object, right? So any API using (void *) for that purpose would > need to be specially wrapped anyway. Am I wrong? Everything in python is an object from at Python 1.0, and probably right from the start. This doesn't mean we can just go on and use python objects for the userInfo argument, because of reference counting: Because the invoked method doesn't know we actually pas in a PyObject* or id, it doesn't know that it should increase the refcount. This means that the object may be garbage collected before it is passed back to us, unless we make sure a reference to it stays alive for as long as needed. I'd prefer not to introduce ways to easily memory corruption bugs in Python programs ;-). BTW. Jack's solution (None->nil, PyCObject->extract the pointer, ...) is a better solution for almost anything with the possible exception of the userInfo arguments in some Cocoa APIs. This does work correctly with 'void*-as-pointer-to-block-of-memory'. BTW2. A python object is _not_ an objective-C object, the pyobjc module just hides the differences. In some instances the difference is important, mostly when Objective-C code doesn't play by the rules (see the iClass example for an example of this) Ronald |
From: Jack J. <Jac...@cw...> - 2002-11-08 11:05:37
|
On Friday, Nov 8, 2002, at 11:31 Europe/Amsterdam, Ronald Oussoren wrote: > BTW. Jack's solution (None->nil, PyCObject->extract the pointer, ...) > is a better solution for almost anything with the possible exception > of the userInfo arguments in some Cocoa APIs. This does work correctly > with 'void*-as-pointer-to-block-of-memory'. So the remaining problem is to decide which of two things a (void *) is. If it is a pointer to a block of memory we should use my method. On the other hand, if it is a callback cookie we should just allow passing of any Python object and show the Python object itself on the receiving side. The latter is fairly easy to implement: the quick-and-dirty-and-dangerous implementation simply does a cast. And if we want to be on the safe side we could use a small wrapper object (so we could check on the receiving side that we're actually getting what we thing we are). The difficult bit, I think, would be to decide which void* argument falls into which category. -- - Jack Jansen <Jac...@or...> http://www.cwi.nl/~jack - - If I can't dance I don't want to be part of your revolution -- Emma Goldman - |
From: Peter M. <zig...@po...> - 2002-11-08 11:55:59
|
Ronald, OK, you've convinced me. I like your passing-an-int idea now. Peter |
From: Jack J. <Jac...@cw...> - 2002-11-08 13:06:32
|
Ronald, I understand from your messages that you've been playing with libffi, but I can't even get it to compile (after manually configuring it, that also failed for OSX). So I guess I'm looking at a different version than you, and/or you know things that I don't. Where did you find libffi, and did you have to do anything special to make it build? -- - Jack Jansen <Jac...@or...> http://www.cwi.nl/~jack - - If I can't dance I don't want to be part of your revolution -- Emma Goldman - |
From: Ronald O. <ous...@ci...> - 2002-11-08 15:10:31
|
I got my copy from the GCC CVS some time ago. I checked out the CVS HEAD and used just the libffi part. The only thing I had to do was a small patch to configure: I kept complaining about a file in .., which probably wasn't there because I didn't build the rest of GCC. As I said, I couldn't get it to build into a shared library. This seems to be caused by an assembler file that is used for closures. Just removing this file is of no use because I actually want to use that feature. Ronald |
From: Jack J. <Jac...@cw...> - 2002-11-11 10:58:32
|
On Friday, Nov 8, 2002, at 16:10 Europe/Amsterdam, Ronald Oussoren wrote: > I got my copy from the GCC CVS some time ago. I checked out the CVS > HEAD and used just the libffi part. The only thing I had to do was a > small patch to configure: I kept complaining about a file in .., which > probably wasn't there because I didn't build the rest of GCC. > > As I said, I couldn't get it to build into a shared library. This > seems to be caused by an assembler file that is used for closures. > Just removing this file is of no use because I actually want to use > that feature. I had a go at it, and by adding a "-read_only_relocs warning" argument to the link call that creates the dylib I managed to get it to work. So, I built a static libffi.a, linked that into a dynamic library (testffi.dylib, in my case) with the -read_only_relocs warning option, and linked against that library with a test program (without any funny options). That worked fine. The ld man page states that relocation in readonly segments of shared libraries is something to be avoided, as the readonly segment will have to be copied and hence no longer can be shared. But, it is only to be *avoided*, it is implemented. And if that doesn't work we should try to fix darwin_closure.S. Without known any PowerPC assembler (i.e. this paragraph should be considered as near-zero-content:-) my first guess is that the jump table at .L60 is the problem. Either the table itself (although the .L44-.L60 form of the entries should have removed any relocation) or the loading of its address, a few lines above. Examining how the C compiler creates code for switch statements if -dynamic is in effect should give us a clue. If we decide to use this I would suggest putting a copy of the code in the PyObjC source tree. The license seems to permit this, it appears to be a very liberal open source license (someone want to check this, please?). And as libffi isn't distributed at the moment the only alternative would be to point people at the gcc CVS tree, which isn't really for the faint of heart. -- - Jack Jansen <Jac...@or...> http://www.cwi.nl/~jack - - If I can't dance I don't want to be part of your revolution -- Emma Goldman - |
From: Ronald O. <ous...@ci...> - 2002-11-11 12:10:56
|
On Monday, Nov 11, 2002, at 11:58 Europe/Amsterdam, Jack Jansen wrote: > > On Friday, Nov 8, 2002, at 16:10 Europe/Amsterdam, Ronald Oussoren > wrote: > >> I got my copy from the GCC CVS some time ago. I checked out the CVS >> HEAD and used just the libffi part. The only thing I had to do was a >> small patch to configure: I kept complaining about a file in .., >> which probably wasn't there because I didn't build the rest of GCC. >> >> As I said, I couldn't get it to build into a shared library. This >> seems to be caused by an assembler file that is used for closures. >> Just removing this file is of no use because I actually want to use >> that feature. > > I had a go at it, and by adding a "-read_only_relocs warning" argument > to the link call that creates the dylib I managed to get it to work. > So, I built a static libffi.a, linked that into a dynamic library > (testffi.dylib, in my case) with the -read_only_relocs warning option, > and linked against that library with a test program (without any funny > options). That worked fine. That is not the most ideal solution, but at least allows us to experiment with using libffi in PyObjC. > > And if that doesn't work we should try to fix darwin_closure.S. > Without known any PowerPC assembler (i.e. this paragraph should be > considered as near-zero-content:-) my first guess is that the jump > table at .L60 is the problem. Either the table itself (although the > .L44-.L60 form of the entries should have removed any relocation) or > the loading of its address, a few lines above. Examining how the C > compiler creates code for switch statements if -dynamic is in effect > should give us a clue. Fixing darwin_closure.S might be usefull anyway. If anyone want to show of their PPC assembly skills: here's your change. I've posted a question about this on the libffi mailinglist, but that seems to be dead. I suppose the developers migrated to the gcc related mailinglists. > > If we decide to use this I would suggest putting a copy of the code in > the PyObjC source tree. The license seems to permit this, it appears > to be a very liberal open source license (someone want to check this, > please?). And as libffi isn't distributed at the moment the only > alternative would be to point people at the gcc CVS tree, which isn't > really for the faint of heart. Yes, including a copy of the code in the PyObjC would be best if we decide to actually use it. That way we can be reasonably sure that the user is using a good version of the library. One reason for looking at libffi was that it's license seems pretty liberal. Ronald |
From: Jack J. <Jac...@cw...> - 2002-11-11 13:54:51
|
On Monday, Nov 11, 2002, at 13:10 Europe/Amsterdam, Ronald Oussoren wrote: >> And if that doesn't work we should try to fix darwin_closure.S. >> Without known any PowerPC assembler (i.e. this paragraph should be >> considered as near-zero-content:-) my first guess is that the jump >> table at .L60 is the problem. Either the table itself (although the >> .L44-.L60 form of the entries should have removed any relocation) or >> the loading of its address, a few lines above. Examining how the C >> compiler creates code for switch statements if -dynamic is in effect >> should give us a clue. > Fixing darwin_closure.S might be usefull anyway. If anyone want to > show of their PPC assembly skills: here's your change. I've posted a > question about this on the libffi mailinglist, but that seems to be > dead. I suppose the developers migrated to the gcc related > mailinglists. A further experiment indicates that the problem is probably the loading of the base address of the jump table. If I compile a switch statement with "cc -static" the base address is loaded with a code sequence similar to the one in darwin_closure.S: lis r9,ha16(L10) la r0,lo16(L10)(r9) If I compile with cc -dynamic (or plain cc, apparently -dynamic is default?) I get a sequence I don't fully understand, but the key bit seems to be bcl 20,31,L1$pb L1$pb: mflr r10 .... addis r9,r10,ha16(L10-L1$pb) la r9,lo16(L10-L1$pb)(r9) so it seems they're using some sort of a relative subroutine jump to get the address of L1$pb into r10, and subsequently address relative to that to get rid of relocation. I've attached the code in case someone wants to have a look. |
From: <bb...@ma...> - 2002-11-08 15:19:11
|
[of course, in the immediate term, we should handle None passed to a (void *) argument as NULL and vice-versa -- this should be pretty easy and takes care of most situations as most callbacks really don't need callback information given that the callback method is executed in the same instance of the class that made the original call and, as such, all of the context is available to the developer anyway.] On Friday, November 8, 2002, at 05:31 AM, Ronald Oussoren wrote: > BTW. Jack's solution (None->nil, PyCObject->extract the pointer, ...) > is a better solution for almost anything with the possible exception > of the userInfo arguments in some Cocoa APIs. This does work correctly > with 'void*-as-pointer-to-block-of-memory'. Why don't we simply limit the calls to methods that take context information to always taking an object reference? This is what the Java Bridge does and, as much as modeling things after the Java bridge is typically a bad idea, it seems like a pretty reasonable solution. In all cases, the context information is produced by the developer and subsequently consumed by the developer-- there is never a case where the AppKit manipulates the context data. In general, the whole MVC design pattern will lead the developer to producing and consuming the context information within the same class. While there could be the rare situation that the developer would produce a value in ObjC to be consumed in Python or vice-versa, this is easily addressed by simply providing cover in one language or the other to handle the conversion across the bridge, as necessary. If we wanted to be particularly tricky, we could use a weak reference type scheme to create a map between (void *) values that were passed across and their corresponding Python object. By maintaining two maps-- Python->ObjC and ObjC->Python-- we could actually map between the Python and ObjC objects as the bridge is crossed. That is, a call that uses a Python encapsulated NSView reference would enter ObjC w/the context information being the (id) of the NSView instance. Similarly, the call back into Python could map back from the NSView instance to the Python object. As long as everything is maintained as weak references-- as straight maps mapping the addresses and nothing more-- this would even work if the developer passes something like [foo userContext: (void *) 1234] across the bridge. The key is to make sure that the weak references are destroyed as the python objects are destroyed (not much we can do on the C side of the bridge-- but not much we need to do, I don't think). -- This doesn't cover NSData, NSImage, and the handful-- very small handful-- of other cases where there is a (void *) method and there isn't some alternative API that can be used instead. Those situations are somewhat of a per-context type issue; i.e. we might need to create specific bridging functionality to support these classes. b.bum b.bum Are you laughing? ... they are. |