digitalmars.D - betterC: new operator
- Dibyendu Majumdar (17/17) Nov 22 2020 I had assumed that new operator is not available in betterC.
- Dennis (4/6) Nov 22 2020 Check out:
- rikki cattermole (4/6) Nov 22 2020 The question was about -betterC.
- Guillaume Piolat (3/5) Nov 22 2020 I think Adam knows how to do it?
- Basile B. (54/71) Nov 22 2020 You can recreate the vtable using static introspection, POC:
- Basile B. (31/43) Nov 22 2020 And the leaks...
- Petar Kirov [ZombineDev] (9/14) Nov 24 2020 Awesome work! I knew it must be possible, but I never tried
- 9il (8/25) Nov 23 2020 Mir's RC classes doesn't use TypeInfo and DRuntime,
- Petar Kirov [ZombineDev] (24/54) Nov 24 2020 Nice! However, how do you initialize the vtbl of the extern (C++)
I had assumed that new operator is not available in betterC. But in following code, it seems the only way to initialize the object correctly ... is there another way I am missing? How should one cleanup objects? import core.stdc.stdio : printf; extern (C++) abstract class A { void sayHello(); } extern (C++) class B : A { override void sayHello() { printf("hello\n"); } } extern (C) void main() { scope b = new B; b.sayHello(); }
Nov 22 2020
On Sunday, 22 November 2020 at 11:54:01 UTC, Dibyendu Majumdar wrote:But in following code, it seems the only way to initialize the object correctly ... is there another way I am missing?Check out: https://p0nce.github.io/d-idioms/#Placement-new-with-emplace
Nov 22 2020
On 23/11/2020 12:57 AM, Dennis wrote:Check out: https://p0nce.github.io/d-idioms/#Placement-new-with-emplaceThe question was about -betterC. This won't work, it depends on TypeInfo. https://github.com/dlang/phobos/blob/master/std/conv.d#L5197
Nov 22 2020
On Sunday, 22 November 2020 at 12:11:39 UTC, rikki cattermole wrote:The question was about -betterC. This won't work, it depends on TypeInfo.I think Adam knows how to do it?
Nov 22 2020
On Sunday, 22 November 2020 at 11:54:01 UTC, Dibyendu Majumdar wrote:I had assumed that new operator is not available in betterC. But in following code, it seems the only way to initialize the object correctly ... is there another way I am missing? How should one cleanup objects? import core.stdc.stdio : printf; extern (C++) abstract class A { void sayHello(); } extern (C++) class B : A { override void sayHello() { printf("hello\n"); } } extern (C) void main() { scope b = new B; b.sayHello(); }You can recreate the vtable using static introspection, POC: --- module a; import core.stdc.stdlib : malloc; import core.stdc.stdio : printf; import std.traits; void setVtable(CT)(ref void** memory) { alias members = __traits(allMembers, CT); void** entries = cast(void**) malloc(members.length + 1); size_t i; static foreach(m; members) static if (isSomeFunction!(__traits(getMember, CT, m))) static foreach (ov; __traits(getVirtualMethods, CT, m)) { entries[i++] = &ov; } memory[0] = *entries; // pointer to vtable memory[1] = null; // monitor memory[2] = null; // interfaces } CT New(CT, A...)(A a) trusted if (is(CT == class)) { enum size = __traits(classInstanceSize, CT); void** memory = cast(void**) malloc(size); setVtable!CT(memory); CT result = cast(CT) &memory; static if (__traits(hasMember, CT, "__ctor")) result.__ctor(a); return result; } extern (C++) class A { abstract void sayHello() {} } extern (C++) class B : A { override void sayHello() { printf("hello\n"); } } extern (C) void main() { B b = New!B(); b.sayHello(); } --- however note 1. not well tested (e.g overloads) 2. static init of fields is not done because that really rquires TypeInfo, so a ctor has to be used instead. But that's a good start to get things done more properly
Nov 22 2020
On Sunday, 22 November 2020 at 16:58:03 UTC, Basile B. wrote:On Sunday, 22 November 2020 at 11:54:01 UTC, Dibyendu Majumdar wrote:And the leaks... More simple solution adapted from http://dpldocs.info/this-week-in-d/Blog.Posted_2020_07_27.html#zero-runtime-classes --- extern(C) int printf(const char*, ...); extern(C++) class A { int omg() { return 12; } } extern(C++) class B : A { override int omg() { return 34; } } template New(T) { pragma(mangle, "_D" ~ T.mangleof[1..$] ~ "6__initZ") __gshared extern immutable ubyte[__traits(classInstanceSize, T)] initializer; T New(ref ubyte[__traits(classInstanceSize, T)] memory) { foreach(idx, ref b; memory) { b = initializer.ptr[idx]; } return cast(T) memory.ptr; } } extern(C) int main() { ubyte[__traits(classInstanceSize, A)] buffer; A a = New!B(buffer); printf("hi %d\n", a.omg()); return 0; } ---I had assumed that new operator is not available in betterC. But in following code, it seems the only way to initialize the object correctly ... is there another way I am missing? How should one cleanup objects?however note 1. not well tested (e.g overloads) 2. static init of fields is not done because that really rquires TypeInfo, so a ctor has to be used instead. But that's a good start to get things done more properly
Nov 22 2020
On Sunday, 22 November 2020 at 16:58:03 UTC, Basile B. wrote:[..] But that's a good start to get things done more properlyAwesome work! I knew it must be possible, but I never tried implementing that. Small bug fix:void** entries = cast(void**) malloc(members.length + 1);Here you're allocating space for (members.length + 1) bytes, while I suppose you actually want to allocate this number of vtbl slots (each being void*.sizeof bytes):auto entries = cast(const(void*)*) malloc((members.length + 1) * (void*).sizeof);I also added `const` for good measure, as the code that the function pointers point to is stored in read-only memory (AFAIK).
Nov 24 2020
On Sunday, 22 November 2020 at 11:54:01 UTC, Dibyendu Majumdar wrote:I had assumed that new operator is not available in betterC. But in following code, it seems the only way to initialize the object correctly ... is there another way I am missing? How should one cleanup objects? import core.stdc.stdio : printf; extern (C++) abstract class A { void sayHello(); } extern (C++) class B : A { override void sayHello() { printf("hello\n"); } } extern (C) void main() { scope b = new B; b.sayHello(); }Mir's RC classes doesn't use TypeInfo and DRuntime, http://mir-algorithm.libmir.org/mir_rc_ptr.html can be used from C++ https://github.com/libmir/mir-algorithm/blob/master/include/mir/rcptr.h https://github.com/libmir/mir.net
Nov 23 2020
On Tuesday, 24 November 2020 at 05:40:21 UTC, 9il wrote:On Sunday, 22 November 2020 at 11:54:01 UTC, Dibyendu Majumdar wrote:Nice! However, how do you initialize the vtbl of the extern (C++) class? I briefly had a look and mir.rc.ptr.createRC [1] calls mir.conv.emplace [2], which is a public import of core.lifetime.emplace, which as far as I can see uses typeinfo for that [3]. You also have a custom typeinfo implementation in mir.typeinfo [4], but I didn't see anything regarding initializing the vtbl pointer in there, just about the pointer to the destructor. Anyway, impressive work on making the interoperability between D, looks much simpler to use then other marshaling techniques for e.g. C/C++. What is the relation between mir.net and autowrap's support for .NET [5]? [1]: https://github.com/libmir/mir-algorithm/blob/2fa78ddb64d5343ae97a8d5acb0012a37d2ae558/source/mir/rc/ptr.d#L263 [2]: https://github.com/libmir/mir-core/blob/8568bf2fceb361ef7804161b1efc5a96e588c24c/source/mir/conv.d#L9 [3]: https://github.com/dlang/druntime/blob/b948c26b8d86be8f058bf538b75df4d422e2a98f/src/core/lifetime.d#L109 [4]: https://github.com/libmir/mir-algorithm/blob/2fa78ddb64d5343ae97a8d5acb0012a37d2ae558/source/mir/type_info.d#L17 [5]: https://github.com/symmetryinvestments/autowrap#generating-net-interfacesI had assumed that new operator is not available in betterC. But in following code, it seems the only way to initialize the object correctly ... is there another way I am missing? How should one cleanup objects? import core.stdc.stdio : printf; extern (C++) abstract class A { void sayHello(); } extern (C++) class B : A { override void sayHello() { printf("hello\n"); } } extern (C) void main() { scope b = new B; b.sayHello(); }Mir's RC classes doesn't use TypeInfo and DRuntime, http://mir-algorithm.libmir.org/mir_rc_ptr.html can be used from C++ https://github.com/libmir/mir-algorithm/blob/master/include/mir/rcptr.h https://github.com/libmir/mir.net
Nov 24 2020
On Tuesday, 24 November 2020 at 11:22:30 UTC, Petar Kirov [ZombineDev] wrote:On Tuesday, 24 November 2020 at 05:40:21 UTC, 9il wrote:`emplace` ref uses type info in compile time. This may not work with betterC flag, I don't know. But it is a compile-time constant, so TypeInfo isn't required to be generated into executable. C++ generates its own vtables. Order of methods should mutch in D and C++, the implementation of a method may be either on the D side or the C++ side. Sometimes you may need to force the C++ compiler to generate vtable using at least one abstract method. vtable for extern(C++) classes is independent of TypeInfo class. But I am not sure how the D compiler generates them. BTW, to make this work, it should be really an extern(C++) interface or abstract classes. So both C++ and D compilers generate vtables. And D has some mangling bugs... but finally weOn Sunday, 22 November 2020 at 11:54:01 UTC, Dibyendu Majumdar wrote:Nice! However, how do you initialize the vtbl of the extern (C++) class? I briefly had a look and mir.rc.ptr.createRC [1] calls mir.conv.emplace [2], which is a public import of core.lifetime.emplace, which as far as I can see uses typeinfo for that [3]. You also have a custom typeinfo implementation in mir.typeinfo [4], but I didn't see anything regarding initializing the vtbl pointer in there, just about the pointer to the destructor.I had assumed that new operator is not available in betterC. But in following code, it seems the only way to initialize the object correctly ... is there another way I am missing? How should one cleanup objects? import core.stdc.stdio : printf; extern (C++) abstract class A { void sayHello(); } extern (C++) class B : A { override void sayHello() { printf("hello\n"); } } extern (C) void main() { scope b = new B; b.sayHello(); }Mir's RC classes doesn't use TypeInfo and DRuntime, http://mir-algorithm.libmir.org/mir_rc_ptr.html can be used from C++ https://github.com/libmir/mir-algorithm/blob/master/include/mir/rcptr.h https://github.com/libmir/mir.netAnyway, impressive work on making the interoperability between mir.net looks much simpler to use than another marshaling techniques for e.g. C/C++. What is the relation between mir.net and autowrap's support for .NET [5]?They are independent projects.
Nov 24 2020
On Tuesday, 24 November 2020 at 17:02:27 UTC, 9il wrote:On Tuesday, 24 November 2020 at 11:22:30 UTC, Petar Kirov [ZombineDev] wrote:>>Nevermind. Hmm, yes, you are right, it uses typeinfo to initialize the payload :/Nice! However, how do you initialize the vtbl of the extern (C++) class? I briefly had a look and mir.rc.ptr.createRC [1] calls mir.conv.emplace [2], which is a public import of core.lifetime.emplace, which as far as I can see uses typeinfo for that [3]. You also have a custom typeinfo implementation in mir.typeinfo [4], but I didn't see anything regarding initializing the vtbl pointer in there, just about the pointer to the destructor.`emplace` ref uses type info in compile time. This may not work with betterC flag, I don't know. But it is a compile-time constant, so TypeInfo isn't required to be generated into executable.
Nov 24 2020