Re: Unexpected behavior when using both alias this and object pointer

2017-01-12 Thread xiren7 via Digitalmars-d-learn

Thanks. Ali.
My previous post is not clear that I have to store class 
reference(object pointer) in void*.


My actual code is try to use libuv in D.

// genarated from uv.h, only two fields is used: 'data', 'type'.
// the document of 'data': "Space for user-defined arbitrary 
data. libuv does not use this field".
// uv_timer_t is the subclass of uv_handle_t in C. (uv_timer_t 
has all the fields defined in uv_handle_t)

struct uv_handle_t {align(8):
union {
struct {void* data; void* _; uv_handle_type type;}
ubyte[96] _payload;
}
}
struct uv_timer_t {align(8):
union {
struct {void* data; void* _; uv_handle_type type;}
ubyte[160] _payload;
}
}
...

// try to resemble the libuv object defined in C.
struct UVHandle {
uv_handle_t _uvHandle;
// subclass uv_handle_t
alias _uvHandle this;

void close() { // uv_close(&this) }
bool isClosing() { // uv_is_closing(&this) }
...
}

// define Timer as 'final class', in order to force Timer 
allocated in gc.

final class Timer {
UVHandle* uvHandle
// subclass UVHandle
alias uvHandle this;
...

this()
{
// malloc memory(nogc) for uv_timer_t.
uvHandle = malloc(uv_timer_t.sizeof)

// store the timer object reference in 'data',
// but 'alias uvHandle this' also overrides 'cast',
// this is the problem described as my previous post.
uvHandle.data = cast(void*) this;
}
~this() { free(uvHandle); }

void start(...) { // uv_timer_start(this.uvHandle, ...) }
void stop() { // uv_timer_stop(this.uvHandle) }
...
}

My current solution is using 'mixin template' instead of 'alias 
this' as the way to subclass:


mixin template UVHandle() { ... }
public final class Timer {
mixin UVHandle;
...
}



Re: Unexpected behavior when using both alias this and object pointer

2017-01-12 Thread Ali Çehreli via Digitalmars-d-learn
Hiding a Foo right after Impl can be a solution. However, you need to 
pass 't', not '&t' to the C function because


- Although it may be unexpected, cast(void*) is the specified way of 
getting the address of a class object


- Taking the address of a class reference (which 't' is one), is just 
the address of the reference itself


So, you either have to do something similar to the following or pass 
void* to the C function.


import std.stdio: writeln;
import core.stdc.stdlib: malloc;

struct Impl {
ubyte[8] payload;
}

struct ImplWithOwner {
Impl impl;
Foo owner;
}

class Foo {
ImplWithOwner *io;

Impl *payload() {
// Guaranteed by D for structs:
assert(cast(void*)io == cast(void*)&io.impl);
return &io.impl;
}

alias payload this;

this() {
io = cast(ImplWithOwner*) malloc(Impl.sizeof);
io.owner = this;
}
}

static Foo asFoo(Impl* p) {
return (cast(ImplWithOwner*)p).owner;
}

extern(C)
void actual_C_function(Impl* data, void function(Impl*) callback) {
data.payload[0] = 42;
callback(data);
}

extern(C)
void myCallback(Impl* p) {
auto foo = p.asFoo;
assert(foo.io.impl.payload[0] == 42);
}

void main() {
auto t = new Foo();
actual_C_function(t, &myCallback);
}

Ali



Unexpected behavior when using both alias this and object pointer

2017-01-12 Thread xiren7 via Digitalmars-d-learn

The problem and the code:

import std.stdio: writeln;
import core.stdc.stdlib: malloc;

struct Impl {
ubyte[8] payload;
}

class Foo {
Impl *impl;
alias impl this;

this()
{
impl = cast(Impl*) malloc(Impl.sizeof);
}
}

class Foo2 {
ubyte[8] payload;
}

void main()
{
// alias T = Foo2;
alias T = Foo;

auto t = new T();

// what I want to do is:
// 1. cast t as pointer
// 2. passe the pointer to a extern(C) callback function
// 3. cast the pointer back to t in extern(C) callback 
function

// 4. accesse the payload field
auto payload = (cast(T) cast(void*) t).payload; // -> crashs

// the right way to get the address of the t object
writeln(*cast(void**) &t);  // -> 278E3373000

// the unexpected behavior
// the obvious(but wrong) way to get the address of the t 
object

writeln(cast(void*) t); // -> 278E164DAB0

// because of alias this
// cast(void*) t == cast(void*) t.payload
writeln(cast(void*) t.payload); // -> 278E164DAB0
}

My question is should let the compiler generate a warning about 
this unexpected(maybe) behavior?




Re: Modify Object Pointer during Initialzation

2014-04-08 Thread Jeroen Bollen

On Tuesday, 8 April 2014 at 14:26:46 UTC, Adam D. Ruppe wrote:

On Tuesday, 8 April 2014 at 14:23:02 UTC, Jeroen Bollen wrote:
Is there a documentation page about the 'uniform function call 
syntax'?


http://dlang.org/function.html#pseudo-member


Oh beat me to it.


Re: Modify Object Pointer during Initialzation

2014-04-08 Thread Adam D. Ruppe

On Tuesday, 8 April 2014 at 14:23:02 UTC, Jeroen Bollen wrote:
Is there a documentation page about the 'uniform function call 
syntax'?


http://dlang.org/function.html#pseudo-member


Re: Modify Object Pointer during Initialzation

2014-04-08 Thread Jeroen Bollen

On Tuesday, 8 April 2014 at 14:23:02 UTC, Jeroen Bollen wrote:
Is there a documentation page about the 'uniform function call 
syntax'?


Never mind, I think I understand all there is to it.


Re: Modify Object Pointer during Initialzation

2014-04-08 Thread Jeroen Bollen

On Tuesday, 8 April 2014 at 14:13:10 UTC, Adam D. Ruppe wrote:

On Tuesday, 8 April 2014 at 14:04:01 UTC, Jeroen Bollen wrote:
Basically, why is this its own variable? Why doesn't D simply 
use the variable it was called with?


A class reference is basically a pointer, passing it by 
reference to each method would be a double pointer and wasted 
effort most the time; all most methods care about is where to 
get the object data, they don't need to know how the caller was 
getting to the object data.


I don't see why this needs to be a new variable and cannot 
simply be 'passed-by-reference'.


You can get that with UFCS btw:

class A {}

void f(ref A a) { /* modify a here and it will change */ }

void main() {
  A a = new A;
  a.f; // a is passed by reference
}


Is there a documentation page about the 'uniform function call 
syntax'?


Re: Modify Object Pointer during Initialzation

2014-04-08 Thread Adam D. Ruppe

On Tuesday, 8 April 2014 at 14:04:01 UTC, Jeroen Bollen wrote:
Basically, why is this its own variable? Why doesn't D simply 
use the variable it was called with?


A class reference is basically a pointer, passing it by reference 
to each method would be a double pointer and wasted effort most 
the time; all most methods care about is where to get the object 
data, they don't need to know how the caller was getting to the 
object data.


I don't see why this needs to be a new variable and cannot 
simply be 'passed-by-reference'.


You can get that with UFCS btw:

class A {}

void f(ref A a) { /* modify a here and it will change */ }

void main() {
  A a = new A;
  a.f; // a is passed by reference
}


Modify Object Pointer during Initialzation

2014-04-08 Thread Jeroen Bollen
This topic is somewhat related to this question I asked yesterday 
on StackOverflow: http://stackoverflow.com/q/22921395/2558778


Basically, why is this its own variable? Why doesn't D simply use 
the variable it was called with?


https://gist.github.com/Binero/10128826

I don't see why this needs to be a new variable and cannot simply 
be 'passed-by-reference'.


Re: Object Pointer

2012-07-18 Thread Jonathan M Davis
On Wednesday, July 18, 2012 20:37:50 Namespace wrote:
> Only for correctness:
> If i allocate memory on the GC Heap in e.g. a struct and don't
> free the memory in the DTor, then the GC free the memory
> automatically?

You don't normally _ever_ free memory from the GC heap. That's the GC's job. 
That's what garbage collectors _do_. There are cases where it may be valuable 
to explicitly free GC memory for performance reasons, but it's risky and opens 
yourself up to the possibility of accessing freed memory and the like. That's 
one of the reasons why delete is being deprecated.

So, no, you don't have to free GC allocated memory in a struct's destructor. 
The GC takes care of it.

- Jonathan M Davis


Re: Object Pointer

2012-07-18 Thread Namespace

Only for correctness:
If i allocate memory on the GC Heap in e.g. a struct and don't 
free the memory in the DTor, then the GC free the memory 
automatically?


Re: Object Pointer

2012-07-16 Thread Jonathan M Davis
On Monday, July 16, 2012 10:31:11 Namespace wrote:
> I'm just experiement with D, that's all. ;)
> Most of my questions here are just out of curiosity.
> 
> I have now this construct:
> 
> [code]
> class smart_ptr {
> private:
>   A* _ptr;
> 
> public:
>   this(A* ptr) {
>   void* buffer = GC.malloc(A.sizeof);
>   memcpy(buffer, ptr, A.sizeof);
> 
>   this._ptr = cast(A*) buffer;
>   }
> 
>   ~this() {
>   GC.free(this._ptr);
>   }
> 
>   @property
>   A* Ptr() {
>   return this._ptr;
>   }
> 
>   alias Ptr this;
> }
> [/code]
> 
> And that is how i use it (ATM):
> 
> [code]
> A a = new A(42);
> smart_ptr sptr = new smart_ptr(&a);
> sptr.echo();
> 
> a = null;
> 
> sptr.echo();
> [/code]
> 
> But how can i free the memory?
> Bizarrely it cannot be delete in the dtor. o.O
> Strange design.

You can't do _anything_ which would allocate or free GC memory in a class 
destructor/finalizer. And even _using_ the GC heap in a class' finalizer is a 
_bad_ idea, because anything to which the object refers to with its member 
variables which is on the GC heap (be it directly or indirectly) may already 
have been collected by the GC (otherwise, it would have problems with circular 
references).

But if you're allocating on the GC heap, you don't _need_ to free anything. 
The GC does that. Class finalizers are for managing resources _other_ than GC 
memory.

- Jonathan M Davis


Re: Object Pointer

2012-07-16 Thread Namespace

I'm just experiement with D, that's all. ;)
Most of my questions here are just out of curiosity.

I have now this construct:

[code]
class smart_ptr {
private:
A* _ptr;

public:
this(A* ptr) {
void* buffer = GC.malloc(A.sizeof);
memcpy(buffer, ptr, A.sizeof);

this._ptr = cast(A*) buffer;
}

~this() {
GC.free(this._ptr);
}

@property
A* Ptr() {
return this._ptr;
}

alias Ptr this;
}
[/code]

And that is how i use it (ATM):

[code]
A a = new A(42);
smart_ptr sptr = new smart_ptr(&a);
sptr.echo();

a = null;

sptr.echo();
[/code]

But how can i free the memory?
Bizarrely it cannot be delete in the dtor. o.O
Strange design.


Re: Object Pointer

2012-07-16 Thread Jonathan M Davis
On Monday, July 16, 2012 09:33:42 Namespace wrote:
> Yes. I want a Pointer of Foo's reference, you're right. I think i
> have to move the reference to the heap?

If you don't want it to point to a local variable and cause problems when it 
goes out of scope, then yeah, though I don't know if it's possible to do that 
or not. Probably, but I'd have to think about it and try out a bunch of stuff 
to be sure. Certainly, you could stick it in a struct and have a pointer to 
the struct.

Regardless, I would point out that you lose polymorphism if you do that. You 
only get polymorphism with references, not pointers. So, you don't want to try 
and call member functions on a class instance through a pointer.

But what you really should be using is std.typecons.Rebindable. If you're 
operating on pointers to class references much, then you're probably doing 
something wrong with your design. Classes really aren't intended to be used 
that way.

- Jonathan M Davis


Re: Object Pointer

2012-07-16 Thread Namespace
You cannot have pointers to classes. The language does not 
support it. You can
have pointers to class references, and you can have pointers to 
structs or the
built-in types, but if Foo is a class, then what you can't have 
a pointer to
it. The closest that you can get is that I believe that you can 
cast class
references to and from void*, and that will work, but Foo* is a 
pointer to a
reference to Foo, not a pointer to Foo, and there's no way in 
the type system

to represent a pointer to Foo.

- Jonathan M Davis


Yes. I want a Pointer of Foo's reference, you're right. I think i 
have to move the reference to the heap?


Re: Object Pointer

2012-07-15 Thread Jonathan M Davis
On Monday, July 16, 2012 00:47:27 Namespace wrote:
> Is something like this possible?
> 
> Foo* create_ptr(Foo f) {
>  assert(f !is null);
>  // ...
> }
> 
> Foo* fp = create_ptr(new Foo());
> 
> with "ref Foo f" of course, there is no limitation.

You cannot have pointers to classes. The language does not support it. You can 
have pointers to class references, and you can have pointers to structs or the 
built-in types, but if Foo is a class, then what you can't have a pointer to 
it. The closest that you can get is that I believe that you can cast class 
references to and from void*, and that will work, but Foo* is a pointer to a 
reference to Foo, not a pointer to Foo, and there's no way in the type system 
to represent a pointer to Foo.

- Jonathan M Davis


Object Pointer

2012-07-15 Thread Namespace

Is something like this possible?

Foo* create_ptr(Foo f) {
assert(f !is null);
// ...
}

Foo* fp = create_ptr(new Foo());

with "ref Foo f" of course, there is no limitation.