GNOME Bugzilla – Bug 659278
Virtual methods in compact classes
Last modified: 2018-03-27 10:16:52 UTC
Created attachment 196767 [details] [review] Patch to allow Berkeley DB-style virtual methods in compact classes in VAPI files I was attempting to write a VAPI definition for Berkeley DB. The interface makes use of “virtual” methods implemented by function pointers in a structure, such as this: int DB->put(DB *db, DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags); To create a VAPI, one would have to create something like: delegate int PutMethod(DB db, Txn txn, DBT key, DBD data, uint32 flags); [Compact] class DB { public PutMethod put; } and then always call it: DB db; db.put(db, ...); Which seems ugly and impractical. I propose allow virtual methods in compact classes in VAPI files that obey this kind of behaviour. So, in the VAPI, have: [Compact] class DB { public virtual int put(Txn txn, DBT key, DBD data, uint32 flags); } And this would allow: db.put(txn, key, data, flags); to generate the C code: db->put(db, txn, key, data, flags); Included is a proposed patch for this behaviour. It does not allow compact classes defined in Vala code to create this behaviour; only to consume it from existing APIs.
I have a workaround for developing a VAPI binding for BDB that allows calling the BDB-style virtual methods. In a supplementary header file: #define VPTR(instance, ...) instance->VPTR_METHOD(instance , ## __VA_ARGS__) Then, in the VAPI binding [Compact] [CCode(free_function = "#undef VPTR_METHOD\n#define VPTR_METHOD free\nVPTR")] class Foo { [CCode(cname = "#undef VPTR_METHOD\n#define VPTR_METHOD a_method\nVPTR")] public extern void a_method(int x); [CCode(cname = "#undef VPTR_METHOD\n#define VPTR_METHOD another_method\nVPTR")] public extern void another_method(); } Vala codegen will convert: foo.a_method(5); into: #undef VPTR_METHOD #define VPTR_METHOD a_method VPTR (foo, 5); and the preprocessor will then generate: foo->a_method(foo, 5); Unfortunately, this requires an extra header (unless there is a better way to inject arbitrary code) and creating a macro that can correctly handle deal with the comma in the function call is not portable. The VTPR macro above uses a GNU extension to drop the comma if the right token of the ## is empty.
If original C is not portable, your solution on a portable header it is good even for the original project, may you want to contribute your workaround to help it to be portable. For Vala compiler no virtual methods should be declared in compact classes and your bindings, using auxiliary declaration works for you, so no Vala related, then closing.
*** This bug has been marked as a duplicate of bug 741465 ***