www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - how to handle memory ownership when interfacing with C/C++ via

reply Timothee Cour <thelastmammoth gmail.com> writes:
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
parent "timotheecour" <timothee.cour2 gmail.com> writes:
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).

 Thanks
Ping? 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