Thread overview
How should class objects created in betterC be destroyed
Nov 06, 2023
zoe
Nov 06, 2023
Imperatorn
Nov 06, 2023
zoe
Nov 06, 2023
zoe
Nov 06, 2023
ryuukk_
Nov 06, 2023
ryuukk_
Nov 07, 2023
zoe
Nov 06, 2023
Paul Backus
November 06, 2023

I customized object.d in -betterc mode and created NEW templates, with modules I can seemingly create classes without extern(C++) mode, and type conversions in function calls seem to work fine. But when destroy doesn't find a way to call the __xtdor() method of the corresponding subclass, is there any way to execute __xtdor() correctly

November 06, 2023

On Monday, 6 November 2023 at 05:30:02 UTC, zoe wrote:

>

I customized object.d in -betterc mode and created NEW templates, with modules I can seemingly create classes without extern(C++) mode, and type conversions in function calls seem to work fine. But when destroy doesn't find a way to call the __xtdor() method of the corresponding subclass, is there any way to execute __xtdor() correctly

Do you have the implementation somewhere?

November 06, 2023

On Monday, 6 November 2023 at 05:52:18 UTC, Imperatorn wrote:

>

On Monday, 6 November 2023 at 05:30:02 UTC, zoe wrote:

>

I customized object.d in -betterc mode and created NEW templates, with modules I can seemingly create classes without extern(C++) mode, and type conversions in function calls seem to work fine. But when destroy doesn't find a way to call the __xtdor() method of the corresponding subclass, is there any way to execute __xtdor() correctly

Do you have the implementation somewhere?

I just define an empty object class, select the object.d file at compile time, and you can use the class, and function parameters can also use the interface

November 06, 2023

On Monday, 6 November 2023 at 05:52:18 UTC, Imperatorn wrote:

>

On Monday, 6 November 2023 at 05:30:02 UTC, zoe wrote:

>

I customized object.d in -betterc mode and created NEW templates, with modules I can seemingly create classes without extern(C++) mode, and type conversions in function calls seem to work fine. But when destroy doesn't find a way to call the __xtdor() method of the corresponding subclass, is there any way to execute __xtdor() correctly

Do you have the implementation somewhere?

// app.d
module app;

import core.stdc.stdio;

interface L
{
void interfaceTest();
}

class Base : L
{

void interfaceTest()
{
puts("call base");
}

~this()
{
puts("destory base");
}
}

class Test : Base
{
int i;
int y;
override void interfaceTest()
{
puts("call test");
}

~this()
{
super.__xdtor();
puts("destory test");
}
}

public void test2(ref Base l)
{
l.interfaceTest();
l.destroy();
}

public void test()
{
Base t = NEW!Test();
test2(t);
}

extern (C) int main()
{
test();
return 0;
}

// object.d
module object;

import core.stdc.stdlib;
import core.stdc.string;
import core.stdc.stdio;

alias size_t = typeof(int.sizeof);
alias ptrdiff_t = typeof(cast(void*) 0 - cast(void*) 0);

alias sizediff_t = ptrdiff_t; // For backwards compatibility only.
// /**
// * Bottom type.
// * See $(DDSUBLINK spec/type, noreturn).
// */
alias noreturn = typeof(*null);

alias hash_t = size_t; // For backwards compatibility only.
alias equals_t = bool; // For backwards compatibility only.

alias string = immutable(char)[];
alias wstring = immutable(wchar)[];
alias dstring = immutable(dchar)[];

T NEW(T, Args...)(auto ref Args args)
{
enum tsize = __traits(classInstanceSize, T);
T t = () @trusted {
import core.stdc.stdlib;

auto _t = cast(T) malloc(tsize);
if (!_t)
  return null;
import core.stdc.string : memcpy;

memcpy(cast(void*) _t, __traits(initSymbol, T).ptr, tsize);
return _t;

}();
if (!t)
return null;
t.__ctor(args);
return t;
}

void destroy(T)(ref T instance)
{
static if (__traits(hasMember, T, "__xdtor") &&
__traits(isSame, T, __traits(parent, instance.__xdtor)))
instance.__xdtor();
() @trusted { import core.stdc.stdio;

free(cast(void*) instance); }();
instance = null;
}

class Object
{
this()
{
}

~this()
{
}
}

// dmd -betterC .\app.d .\object.d or ldmd2 -betterC -m64 .\app.d .\object.d
The destroy method does not find exactly what the subclass object should be

November 06, 2023
Please tag your code accordingly, as is it's unreadable


```D
// your code here
```

(tick the "Enable Markdown" too, next to the Send button)
November 06, 2023

Here is how adam seems to be doing it: https://github.com/adamdruppe/webassembly/blob/731a7033174127c0a6dd4f23eabdb440adab286b/arsd-webassembly/object.d#L650-L681

Specially here:

void destroy(bool initialize = true, T)(T obj) if (is(T == class))
{
(..)
    else
    {
        // Bypass overloaded opCast
        auto ptr = (() @trusted => *cast(void**) &obj)();
        rt_finalize2(ptr, true, initialize);
    }
}

and for interface:

cast(Object)obj

But i suspect you'll have to implement the whole typeinfo

November 06, 2023

On Monday, 6 November 2023 at 05:30:02 UTC, zoe wrote:

>

I customized object.d in -betterc mode and created NEW templates, with modules I can seemingly create classes without extern(C++) mode, and type conversions in function calls seem to work fine. But when destroy doesn't find a way to call the __xtdor() method of the corresponding subclass, is there any way to execute __xtdor() correctly

Unfortunately, D classes cannot have virtual destructors, so TypeInfo is the only way to find the correct derived class destructor to call at runtime.

I think the best you can do is implement your own virtual destructors, and your own destroy function that knows how to call them; for example:

interface BettercDestructible
{
    void destruct() nothrow @nogc;
}

class MyClass : BettercDestructible
{
    // ...
    override void destruct()
    {
        // destructor implementation here
    }

    ~this() { this.destruct(); }
}

void destroy(BettercDestructible obj)
{
    obj.destruct();
}

Of course, for classes that don't implement BettercDestructible, you're still out of luck, but it's better than nothing.

November 07, 2023

On Monday, 6 November 2023 at 16:08:41 UTC, ryuukk_ wrote:

>

Here is how adam seems to be doing it: https://github.com/adamdruppe/webassembly/blob/731a7033174127c0a6dd4f23eabdb440adab286b/arsd-webassembly/object.d#L650-L681

Specially here:

void destroy(bool initialize = true, T)(T obj) if (is(T == class))
{
(..)
    else
    {
        // Bypass overloaded opCast
        auto ptr = (() @trusted => *cast(void**) &obj)();
        rt_finalize2(ptr, true, initialize);
    }
}

and for interface:

cast(Object)obj

But i suspect you'll have to implement the whole typeinfo
Thanks, I found out later that I couldn't use the cast keyword