On Thursday, 4 April 2024 at 09:52:14 UTC, Valthorn wrote:
> Hello, today I wrote the following code to try out ImportC:
// functions.c
#include <stdio.h>
#include <stdlib.h>
void allocateMemory() {
int *data = (int *)malloc(1024 * 1024 * sizeof(int));
if (data == NULL) {
fprintf(stderr, "Memory could not be allocated.\n");
exit(EXIT_FAILURE);
}
printf("4MB of memory allocated.\n");
}
// demo.d
import std.stdio;
import core.memory;
import functions;
void main() {
writeln("Before allocating memory. Memory: ", GC.stats().usedSize, " bytes");
allocateMemory();
writeln("After allocating memory. Memory: ", GC.stats().usedSize, " bytes");
GC.collect();
writeln("GC.collect() was called. Memory: ", GC.stats().usedSize, " bytes");
}
Here I tried to check the operation of GC with ImportC, but there's a situation I'm curious about. How exactly does ImportC work?
Think of it as if you compiled all of your C files into a library, wrote wrappers on the D side, and called the library functions from your D code. The only parts of D that are available to your C code are things you explicitly import using __import
. I suppose it's possible that you could import everything needed to use D's GC from C. However, the primary use is to use legacy C code from D.
If you want some memory in your C program that is managed by D's GC, you can do this:
- Write an allocation function in a D module that allocates GC memory, using GC.addRoot to protect it from being collected, and return that memory from the function.
- Write a function to free in the D module that calls GC.removeRoot to tell the GC that it's eligible for collection.
- Import that module in your C code using an
__import
statement. Call the allocate function when you need the memory and call the free function when you're done.
I've actually done this to allow the use of associative arrays from C. It's probably not something that would be used often unless you're using ImportC to as a mechanism to improve your C code. In my case, the goal was to eliminate a dependency on glib.