Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
July 27, 2015 Problem with casting instance reference to void* and back. | ||||
---|---|---|---|---|
| ||||
Hi! My use case requires interaction with C API which in turn implies storing object instance reference as void *. I'm using gdc 4.9.2 and everything worked fine with "object -> void * -> object" conversion, but "object -> void * -> interface" failed. The stripped-down example is something like this: interface TestInterface { void testMethod(); } class TestImpl : TestInterface { void testMethod() { writefln("TestImpl::testMethod\n"); } }; void testDispathcer(void *rawSelf) { auto self = cast(TestInterface) rawSelf; // nothing happens self.testMethod(); } int main(string[] args) { auto t = new TestImpl(); testDispathcer(cast(void *) t); return 0; } However this works: void testDispathcer(TestImpl rawSelf) { auto self = cast(TestInterface) rawSelf; // TestImpl::testMethod is printed to stdout self.testMethod(); } int main(string[] args) { auto t = new TestImpl(); testDispathcer(t); return 0; } Is there any way to handle such situation without resorting to templating dispatcher with every *Impl type? As second example works as expected I presume that runtime loses some type information to perform downcast and maybe it's possible to extract it and store externally and merge back later? I'm quite new to D and sorry if the question is dumb. Any help would be greatly appreciated! Thanks in advance! |
July 27, 2015 Re: Problem with casting instance reference to void* and back. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vlad Leberstein | On Monday, 27 July 2015 at 12:03:06 UTC, Vlad Leberstein wrote: > Hi! My use case requires interaction with C API which in turn implies storing object instance reference as void *. I'm using gdc 4.9.2 and everything worked fine with "object -> void * -> object" conversion, but "object -> void * -> interface" failed. The stripped-down example is something like this: > > interface TestInterface { > void testMethod(); > } > > class TestImpl : TestInterface { > void testMethod() { > writefln("TestImpl::testMethod\n"); > } > }; > > void testDispathcer(void *rawSelf) { > auto self = cast(TestInterface) rawSelf; > // nothing happens > self.testMethod(); > } > > > int main(string[] args) { > auto t = new TestImpl(); > testDispathcer(cast(void *) t); > return 0; > } > > However this works: > > void testDispathcer(TestImpl rawSelf) { > auto self = cast(TestInterface) rawSelf; > // TestImpl::testMethod is printed to stdout > self.testMethod(); > } > > > int main(string[] args) { > auto t = new TestImpl(); > testDispathcer(t); > return 0; > } > > Is there any way to handle such situation without resorting to templating dispatcher with every *Impl type? As second example works as expected I presume that runtime loses some type information to perform downcast and maybe it's possible to extract it and store externally and merge back later? > > I'm quite new to D and sorry if the question is dumb. Any help would be greatly appreciated! Thanks in advance! In the first example, you pass a pointer to a class instance. You cannot get the vtbl entry for the interface like this. Instead try to do this in 2 steps: --- import std.stdio; interface TestInterface { void testMethod(); } class TestImpl : TestInterface { void testMethod() { writefln("TestImpl::testMethod\n"); } }; void testDispathcer(void *rawSelf) { auto obj = cast(Object) rawSelf; auto self = cast(TestInterface) obj; // nothing happens self.testMethod(); } int main(string[] args) { auto t = new TestImpl(); testDispathcer(cast(void *) t); return 0; } --- |
July 27, 2015 Re: Problem with casting instance reference to void* and back. | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | On Monday, 27 July 2015 at 13:11:33 UTC, anonymous wrote:
> In the first example, you pass a pointer to a class instance. You cannot get the vtbl entry for the interface like this. Instead try to do this in 2 steps:
actually i meant you pass an untyped pointer, so when you cast as interface it's not like if the vtbl of an object is queried. So you have to upcast to an Object then cast to the interface, which is not a simple cast (it get something in the virtual table.
void testDispathcer(void *rawSelf) {
auto obj = cast(Object) rawSelf; // reinterpret
auto self = cast(TestInterface) obj; // get vtbl entry , it's not a simple cast
// works
self.testMethod();
}
|
July 27, 2015 Re: Problem with casting instance reference to void* and back. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vlad Leberstein | On 07/27/15 14:03, Vlad Leberstein via Digitalmars-d-learn wrote: > Hi! My use case requires interaction with C API which in turn implies storing object instance reference as void *. I'm using gdc 4.9.2 and everything worked fine with "object -> void * -> object" conversion, but "object -> void * -> interface" failed. The stripped-down example is something like this: > > interface TestInterface { > void testMethod(); > } > > class TestImpl : TestInterface { > void testMethod() { > writefln("TestImpl::testMethod\n"); > } > }; > > void testDispathcer(void *rawSelf) { > auto self = cast(TestInterface) rawSelf; > // nothing happens > self.testMethod(); > } > > > int main(string[] args) { > auto t = new TestImpl(); > testDispathcer(cast(void *) t); > return 0; > } > Is there any way to handle such situation without resorting to templating dispatcher with every *Impl type? auto self = cast(TestInterface)cast(Object) rawSelf [you should probably check for null, and consider using a reinterpret-cast (`testDispathcer(*cast(void **)&t)`) because a "normal" one can be overridden by the class, sometimes accidentally] artur |
July 27, 2015 Re: Problem with casting instance reference to void* and back. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Artur Skawina | > auto self = cast(TestInterface)cast(Object) rawSelf
Works like a charm! Thank you both!
|
Copyright © 1999-2021 by the D Language Foundation