Very cool idea! Tried to allow the interface to be implemented implicitly:
type
Interface = object
obj: pointer
vtable: MethodTable
MethodTable = object
foo: proc(this: pointer): int
proc toInterface[T](t: var T): Interface =
let this = addr t
let table {.global.} = MethodTable(
foo: proc (this:pointer):int = cast[ptr T](this).foo
)
result = Interface(obj: this, vtable: table)
proc foo(this: Interface): int =
this.vtable.foo(this.obj)
type
A = object
B = object
proc foo(a: ptr A): int = 3
proc foo(a: ptr B): int = 5
var
a = A()
b = B()
a_i = toInterface(a)
b_i = toInterface(b)
c = @[a_i, b_i]
for e in c:
echo e.foo()
Works with two caveats: If toInterface is a converter and you try to use it
implicitly nim generates illegal c code. And if toInterface is defined after
exactly one implementation of foo() it breaks with
> type mismatch: got (ptr A) but expected one of: proc foo(this: Interface): int
If toInterface is a converter nim just straight up hangs up. If toInterface
comes first or at least two foo()'s are defined before it everything works fine.