Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new FFI method: attach_method #49

Closed
wants to merge 1 commit into from

Conversation

@pipcet
Copy link
Contributor

commented Mar 7, 2015

NOTE: I've implemented the changes I thought of as I was submitting the first pull request, and they're at https://github.com/plicease/FFI-Platypus/compare/master...pipcet:attach-object-method?expand=1. That includes documentation and tests, as well as some bug fixes.

it works like attach, but generates an XSUB which will check its first
argument to be the right object before discarding it and calling a C
function with the remaining arguments.

The tricky part is that the XSUB can be shared between different objects using different libraries and, in future, different "implementations". We cache the last function we've used, so performance should be very good in the typical case, but I haven't tested it. I've learned my lesson about hash lookups in inner loops, so we avoid that.

Now that I've written it, it occurs to me that it might be more useful behavior not to discard the first "object" method, but the specific application I had in mind requires it, and we can always add $ffi->attach_object_method($object, [object_function=>method], ['object'] =>'object') to handle that case.

Note that unlike ->attach, there is no reason we need to lock things into memory permanently: when $object is destroyed, the weak references to it will vanish and the hash entry it refers to will go stale; if necessary, we can even clean up stale hash entries once in a while (I'm not sure whether there is a Perl way of implementing a hash with weak keys, but that's what we'd use).

About the use case: I'm attaching to gdb, which has a function called parse_expression, with a const char * argument and an opaque pointer return value, which I want to call as $gdb->parse_expression($string). Simply using ->attach would pass $gdb as the first argument, which breaks things, and using a wrapper is both slow and limited to a single object, and of course writing a wrapper sub for each method is out of the question.

On second thought, it might be better to define attach_method to work like this:

$ffi->attach_method($object, [function=>'method'] => ['object', 'int'] => 'opaque') makes $object->method(7) call function($object, 7) using $ffi's implementation and its library handles.

$ffi2->attach_method($object, [function=>'method'] => ['void', 'int'] => 'opaque') makes $object->method(7) call function(7) using $ffi2's implementation. (A 'void', in my head, is a type that translates a single Perl argument to zero native arguments on the stack, which is what we want in this case).

$ffi3->attach_method([$object=>$address], [function=>'method'] => ['opaque', 'int'] => 'opaque') makes $object->method(7) call function($address, 7) using $ffi3's implementation.

both of these or multiple variants of either can be combined in the same package.

What do you think? Sorry this got a bit long, but I feel it might be an interesting feature to have. It would be good to decide whether to use the explicit-'void' API or the implicitly discarding API before shipping anything, of course.

new FFI method: attach_method
it works like attach, but generates an XSUB which will check its first
argument to be the right object before discarding it and calling a C
function with the remaining arguments.
@plicease

This comment has been minimized.

Copy link
Member

commented Mar 11, 2015

I was thinking about implementing an attach_method. I'm glad that I saved it for later, because I think you've done some good thinking about it. I haven't had the time yet to look closely at this yet this week because of $work. I do intend on looking at this next week hopefully.

@pipcet

This comment has been minimized.

Copy link
Contributor Author

commented Mar 11, 2015

Don't worry about taking your time, it's not like the patch will go bad. Thanks for looking at it, though if you don't mind I'll prepare a new pull request with my current version sometime this week.

We can also postpone discussing other changes until then. I think I've made a good start on #44 , and some work on performance using @calid's excellent work at https://gist.github.com/calid/17df5bcfb81c83786d6f. I'm quite excited I'll be able to properly benchmark the attach_method code soon.

@plicease

This comment has been minimized.

Copy link
Member

commented Jul 23, 2019

I apologize for the long lead time to this response!

I've decided to go with #151 to implement method type interfaces. There is a lot that I like about your approach, but I finally decided that implementing class level methods with an "object" type is more flexible and covers more use cases. Now that Platypus supports anonymous code references (like attach but without a name), I think that you can implement most of what you can do with the method_attach approach with Object::Method and function objects / anonymous code references.

@plicease plicease closed this Jul 23, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.