digitalmars.D.learn - how to handle memory ownership when interfacing with C/C++ via
- Timothee Cour (46/46) Oct 10 2013 Short version:
- timotheecour (19/72) Oct 15 2013 Ping?
Short version: I have a struct A* aptr allocated in C/C++ with an internal pointer aptr->ptr (say a double*) I want to store a reference x (say double[]) in D to aptr only through aptr->ptr, not through aptr directly as it's inconvenient in my use case. How do I achieve that, so that when x goes out of scope, some deallocator for aptr will be called ? Long version: ---- suppose I have C++ code: struct A{ double*ptr; A(size_t n){ptr=(double*)malloc(n);} ~A(){free(ptr);} }; and a D wrapper around it: extern(C){struct A; A*A_new(size_t n); void A_delete(A*a); double*A_ptr(A*a);} I want to use it as follows: double[] get_x(size_t n){ return A_new(n).A_ptr[0..n]; } void main(){ double[]x=get_x(n); // do something with x; } ---- It's trivial to handle this via a class wrapper: class A2{ A*a; this(size_t n){a=A_new(n);} ~this(){A_delete(n);} double*ptr(){return A_ptr(a);} } double[] get_x(size_t n){ auto a2=new A2(n); return a2.ptr; //this doesn't help much though, A2 will go out of scope when this function exits. } but I don't want to maintain objects of class A2 around, just double[] slices as above. Is there some magic involving core.memory.addRoot,addRange (etc) I can use so that a2 stays alive as long as x stays alive? (in which case when x goes out of scope, 'a2' will too, and will call A_delete). Thanks
Oct 10 2013
On Thursday, 10 October 2013 at 23:02:29 UTC, Timothee Cour wrote:Short version: I have a struct A* aptr allocated in C/C++ with an internal pointer aptr->ptr (say a double*) I want to store a reference x (say double[]) in D to aptr only through aptr->ptr, not through aptr directly as it's inconvenient in my use case. How do I achieve that, so that when x goes out of scope, some deallocator for aptr will be called ? Long version: ---- suppose I have C++ code: struct A{ double*ptr; A(size_t n){ptr=(double*)malloc(n);} ~A(){free(ptr);} }; and a D wrapper around it: extern(C){struct A; A*A_new(size_t n); void A_delete(A*a); double*A_ptr(A*a);} I want to use it as follows: double[] get_x(size_t n){ return A_new(n).A_ptr[0..n]; } void main(){ double[]x=get_x(n); // do something with x; } ---- It's trivial to handle this via a class wrapper: class A2{ A*a; this(size_t n){a=A_new(n);} ~this(){A_delete(n);} double*ptr(){return A_ptr(a);} } double[] get_x(size_t n){ auto a2=new A2(n); return a2.ptr; //this doesn't help much though, A2 will go out of scope when this function exits. } but I don't want to maintain objects of class A2 around, just double[] slices as above. Is there some magic involving core.memory.addRoot,addRange (etc) I can use so that a2 stays alive as long as x stays alive? (in which case when x goes out of scope, 'a2' will too, and will call A_delete). ThanksPing? Is anything above unclear? here are more details (in a simplified setting): say, I have an image class D_image which has fields: ubyte* ptr //pointer to memory uint[2] size; I'd like to interface with, say, a swig-wrapped opencv C++ image class Swig_image, so that when an object d_image:D_image goes out of scope (and its pointer ptr also goes out of scope), (with d_image constructed from an object swig_image of type Swig_image), then swig_image will also go out of scope. again, this can be done by adding a field to D_image (say of type void* to make it work with any source), buy I'm wondering whether this can be achieved without adding this field, with some GC magic associating a pointer (ptr) to another pointer (cast(void*) swig_image). This would make interfacing with C++ libs much easier as there would be no bookkeeping in user code.
Oct 15 2013