digitalmars.D - ImportC with Garbage Collector
Hello, today I wrote the following code to try out ImportC: ```c // 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"); } ``` ```d // 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? Can't it be used together with GC? Might there be an ImportC update in the future that will also encompass the GC?
Apr 04
On Thursday, 4 April 2024 at 09:52:14 UTC, Valthorn wrote:Hello, today I wrote the following code to try out ImportC: ```c // 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"); } ``` ```d // 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? Can't it be used together with GC? Might there be an ImportC update in the future that will also encompass the GC?That would make sense if you posted on Learn by the way. The thing is that `malloc` is completely unrelated to the `GC`. If you want to allocate using the garbage collector, in D, you would need to `import core.memory; GC.malloc(size);`. For usage in C, you would need to export that function and use it in C. Also, managing a GC without a runtime is way harder since there is a lot of internal functions that mark your memory somehow for not collecting the memory you allocated. That being said, IMO, importC should be preferred to only importing C code, and not for D code interaction since one would rather simply use D.
Apr 04
On Thursday, 4 April 2024 at 09:52:14 UTC, Valthorn wrote:Hello, today I wrote the following code to try out ImportC: ```c // 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"); } ``` ```d // 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: 1. 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. 2. Write a function to free in the D module that calls GC.removeRoot to tell the GC that it's eligible for collection. 3. 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.
Apr 04