I am trying to compile the following code in D
void* instantiate(_LV2_Descriptor* descriptor,
double sample_rate, char * bundle_path,
LV2_Feature** features) {
Plugin plugin = new Bleep(sample_rate, features);
return &plugin;
}
but I get the following error
../src/lv2/plugin.d(38): Error: escaping reference to local plugin
What is the right way to create a class instance and a return it as a pointer? Also in such a way that it is not claimed by GC. There is another callback for object deletion.
Plugin and Bleep are clearly classes given that you're assigning a new Bleep to a Plugin variable, and there's no * on plugin's declaration. So, plugin is a reference, not a pointer. &plugin is returning a pointer to a reference - in this case, one which is a local variable (hence the error). It's not what you want at all. You can explicitly cast plugin to void* if you really want a pointer, but that is a somewhat abnormal thing to do. I assume that you're interfacing with C code, otherwise there really shouldn't be a reason to cast to void*. Class objects are references, not pointers, and should be left as such if possible. If you're passing it to C code (presumably which will then call your D code later, since C doesn't know what to do with a D class), then you're more or less stuck using void*, but I'd advise avoiding it otherwise.
The GC won't free the object as long as your D code has a reference to it, but if you pass it to a C function and don't leave any reference to it in your D code, it will be collected at some point by the GC.
If you're going to be explicitly freeing the object yourself, then don't use the GC. delete is scheduled for deprecation, and you're not normally supposed to be freeing stuff on the GC heap yourself. That's the GC's job. You can call destroy on an object to destroy it (e.g. destroy(obj);), but the memory won't be freed (rather the destructor will be called, and the object's vtable will be zeroed out so that using it will result in a segfault).
If you really want to be allocating and deallocating an object yourself, then you should be using malloc and free, though that's definitely more complicated. You'd have to allocate a chunk of memory the size of the object with malloc, and then use std.conv.emplace to construct the class in that chunk of memory in order to create the object. Then to free it, you'd have to explicitly call its destructor, and then call free on that memory. Work is being done on custom allocators which should definitely make this easier (probably making it much closer to alloc.new!MyClass(args) and alloc.free(obj)), but they haven't been completed yet and so aren't yet in the standard library.
One way to handle allocating and freeing the object using the GC if you don't need deterministic destruction would be to simply keep a reference to the object in your D code and then set that reference to null when you want to free the object. It won't free it until the GC decides to collect it, but it makes it so that the GC won't collect before you're done with it and so that it will be able to collect it once you are.
just return the plugin it is already a pointer
also as long as you keep a reference to it, it won't be claimed by GC
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With