-
Notifications
You must be signed in to change notification settings - Fork 14
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
Remember existing Ruby wrappers for GObjects #63
Comments
I'm struggling with this one. Is there a solution on the horizon? |
I'm afraid I have nothing planned at the moment. |
I'm playing with |
Once this is working I can stop storing user-defined properties in C struct fields, which should reduce the some of the ref_count increases that happen in #82. |
I'd be willing to work on this but I don't know where to start. |
The below, basic patch seems to help. I can observe that my instance is re-used and its instance variable survive (the native code creates the object and then immediately calls a interface vfunc). I'm sure it's not complete yet. I guess at least removing from What do you think of it? diff --git a/lib/gir_ffi/class_base.rb b/lib/gir_ffi/class_base.rb
index 4b401bc..0e71939 100644
--- a/lib/gir_ffi/class_base.rb
+++ b/lib/gir_ffi/class_base.rb
@@ -11,6 +11,13 @@ module GirFFI
extend Forwardable
GIR_FFI_BUILDER = Builders::NullClassBuilder.new
+ @object_cache = {}
+
+ def self.inherited(klass)
+ klass.class_eval do
+ @object_cache = {}
+ end
+ end
attr_reader :struct
def_delegators :@struct, :to_ptr
@@ -73,7 +80,11 @@ module GirFFI
# do any casting to subtypes or additional processing.
def self.direct_wrap(ptr)
return nil if !ptr || ptr.null?
- obj = allocate
+ # try to use existing object from cache
+ unless obj = @object_cache[ptr.address]
+ obj = allocate
+ @object_cache[ptr.address] = obj
+ end
obj.__send__ :assign_pointer, ptr
obj
end
@@ -100,7 +111,12 @@ module GirFFI
end
def assign_pointer(ptr)
+ _self = self
@struct = self.class::Struct.new(ptr)
+ self.class.class_eval do
+ @object_cache[ptr.address] = _self
+ end
+ @struct
end
end
end |
Let's back up a little bit. Can you show me what you need this feature for? My original intention was to use it to be able to store properties as Ruby instance variables, but with the recent enhancements of the user-defined properties that seems less urgent. So, can you show me a bit more of what you're trying to achieve? |
Your patch looks reasonable, by the way. |
I'll describe my project, hopefully that explain this and other requirements. If you don't know libpeas: It's a library originated in the GNOME world that implements a plugin interface and loaders for non-C languages. C-based programs can use this, other ones too since libpeas also provides introspection data for itself. Programs using this library can easily support written in other languages, most notably python and lua at the moment. I'm working on adding Ruby to the list. Some prominent users of libpeas are gedit, eog, gitg and Geany (through a plugin that I developed). So, for a libpeas loader there are some requirements: 1) Usable objects can be created from native code; the native code works with the GObject (or derived) pointer. 2) The objects implement GObject interfaces, 3) the loaders have some bindings to the GTK stack, preferably GI-based as libpeas does not provide such by itself. The bindings can be gir_ffi or ruby-gnome2 but I'm focussing on gir_ffi. For 1, there is a specialized function that the programs call ( For 2, Ruby context is only entered through the interface methods (setup by gir_ffi). Between those invocations the proxy object (Ruby object here) must maintain state. My current state is that I call into Ruby when an extension is created. The backing loader implementation of I've pushed my current state onto github, see https://github.com/kugel-/libpeas/tree/ruby. The tests give some idea how the library is used, for example here: https://github.com/kugel-/libpeas/blob/ruby/tests/libpeas/extension-rbffi.c#L52 |
@kugel- thanks, I'll take a look. |
Just a note: My intent was always that subclasses defined in Ruby should still store all their state in properties, which are stored in C data. This is a little more complicated than using instance variables, but it should work. Ruby-GNOME uses the other approach and stores even properties as ivars. |
I'd like to come back to this. What do you think is missing from the patch I posted above? |
If a Ruby wrapper already exists for a given GObject, GirFFI should not create a new wrapper but instead return the existing one. Ruby-GNOME2 and PyGobject store the wrapper in the GObject's qdata.
Keeping this wrapper around allows storing the properties for a derived type as Ruby instance variables instead of extending the C struct of the parent type.
The text was updated successfully, but these errors were encountered: