digitalmars.D.learn - Calling D code from C
- Niko Korhonen (38/38) May 26 2005 I'm playing around with an idea to make my D library partially callable
- Vathix (22/60) May 26 2005 The problem is that D's main() initializes things. Using a C main()
- Niko Korhonen (4/8) May 27 2005 Thanks a million, that fixed the problem! BTW, is anything about this
- Stefan (31/35) Jan 08 2020 That's correct, but not always an option, such as when writing a
- H. S. Teoh (11/19) Jan 08 2020 [...]
- Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= (5/24) Jan 08 2020 What is going on here? The original post date appears as to be of
- H. S. Teoh (7/9) Jan 08 2020 [...]
- bachmeier (2/10) Jan 08 2020 Google is good at resurrection.
I'm playing around with an idea to make my D library partially callable in C. Getting C and D to interface with each other is something totally new for me, and thus I've stumbled into a weird problem. Consider the following short programs: ctest.d: (D code) <code> module ctest; extern (C) { void test() { int[] x = new int[10]; printf("x.length: %u\n", x.length); } } </code> ctest-c.c: (C code) <code> void test(void); // Declare the D function int main() { test(); return 0; } </code> The purpose is to compile the D file into an obj, compile the C file and link it with the D obj file. When I do this using DMD/DMC in the following way: <code> dmd -c ctest.d dmc ctest-c.c ctest.obj c:\tools\dmd\lib\phobos.lib </code> It works correctly, but when executing ctest-c.exe, it crashes with a trying to write to a null pointer message. Apparently the 'new' clause in the D file causes the crash. Should this work, or have I missed something very important in C/D interoperability? For instance, is it forbidden to use D memory management facilities or something like that?
May 26 2005
On Thu, 26 May 2005 16:18:21 -0400, Niko Korhonen <niktheblak hotmail.com> wrote:I'm playing around with an idea to make my D library partially callable in C. Getting C and D to interface with each other is something totally new for me, and thus I've stumbled into a weird problem. Consider the following short programs: ctest.d: (D code) <code> module ctest; extern (C) { void test() { int[] x = new int[10]; printf("x.length: %u\n", x.length); } } </code> ctest-c.c: (C code) <code> void test(void); // Declare the D function int main() { test(); return 0; } </code> The purpose is to compile the D file into an obj, compile the C file and link it with the D obj file. When I do this using DMD/DMC in the following way: <code> dmd -c ctest.d dmc ctest-c.c ctest.obj c:\tools\dmd\lib\phobos.lib </code> It works correctly, but when executing ctest-c.exe, it crashes with a trying to write to a null pointer message. Apparently the 'new' clause in the D file causes the crash. Should this work, or have I missed something very important in C/D interoperability? For instance, is it forbidden to use D memory management facilities or something like that?The problem is that D's main() initializes things. Using a C main() bypasses that startup code. Put the main() in the D file (with D extern) and have it call a function in the C file that you will treat as main. (D code) extern(C) { int cmain(); void test() { printf("test!\n"); } } int main() { return cmain(); } (C code) void test(void); int cmain(void) { test(); return 0; }
May 26 2005
Vathix wrote:The problem is that D's main() initializes things. Using a C main() bypasses that startup code. Put the main() in the D file (with D extern) and have it call a function in the C file that you will treat as main.Thanks a million, that fixed the problem! BTW, is anything about this mentioned in the docs/FAQs? I couldn't find anything when I tried to google for this issue.
May 27 2005
On Thursday, 26 May 2005 at 20:41:10 UTC, Vathix wrote:The problem is that D's main() initializes things. Using a C main() bypasses that startup code. Put the main() in the D file (with D extern) and have it call a function in the C file that you will treat as main.That's correct, but not always an option, such as when writing a D library which can be called from C programs you can't touch. But you can easily do the initialization in your D code, by calling rt_init() and rt_term(), like this: import std.stdio; import core.memory : GC; extern(C) int rt_init(); extern(C) int rt_term(); extern(C) __gshared bool rt_initialized = false; extern(C) void d_function(){ writeln("Initializing D runtime"); if(!rt_initialized) rt_init(); rt_initialized = true; char[] big = new char[10000000]; big = null; writeln("Calling GC"); GC.collect(); writeln("Finishing D function"); scope(exit){ writeln("Terminating D runtime"); if(rt_initialized) rt_term(); rt_initialized = false; } } ...just be careful that you don't do anything requiring memory allocation before rt_init() or after rt_term().
Jan 08 2020
On Wed, Jan 08, 2020 at 06:12:01PM +0000, Stefan via Digitalmars-d-learn wrote: [...]But you can easily do the initialization in your D code, by calling rt_init() and rt_term(), like this:[...]extern(C) int rt_init(); extern(C) int rt_term(); extern(C) __gshared bool rt_initialized = false;[...]if(!rt_initialized) rt_init(); rt_initialized = true;I believe the rt_initialized flag is unnecessary, because rt_init/rt_term use an atomic counter to keep track of how many times they were called. So you just have to call rt_init and make sure you have a matching call to rt_term, and it should Just Work(tm). T -- The richest man is not he who has the most, but he who needs the least.
Jan 08 2020
On Wednesday, 8 January 2020 at 19:05:29 UTC, H. S. Teoh wrote:On Wed, Jan 08, 2020 at 06:12:01PM +0000, Stefan via Digitalmars-d-learn wrote: [...]What is going on here? The original post date appears as to be of 2005 :D. And a reminder that druntime must be linked along with phobos when it is a library.But you can easily do the initialization in your D code, by calling rt_init() and rt_term(), like this:[...]extern(C) int rt_init(); extern(C) int rt_term(); extern(C) __gshared bool rt_initialized = false;[...]if(!rt_initialized) rt_init(); rt_initialized = true;I believe the rt_initialized flag is unnecessary, because rt_init/rt_term use an atomic counter to keep track of how many times they were called. So you just have to call rt_init and make sure you have a matching call to rt_term, and it should Just Work(tm). T
Jan 08 2020
On Wed, Jan 08, 2020 at 09:42:03PM +0000, Ferhat Kurtulmuş via Digitalmars-d-learn wrote: [...]What is going on here? The original post date appears as to be of 2005 :D.[...] Haha yeah, I'm not sure why Stefan replied to a post dating from 2005. T -- Just because you can, doesn't mean you should.
Jan 08 2020
On Wednesday, 8 January 2020 at 22:00:03 UTC, H. S. Teoh wrote:On Wed, Jan 08, 2020 at 09:42:03PM +0000, Ferhat Kurtulmuş via Digitalmars-d-learn wrote: [...]Google is good at resurrection.What is going on here? The original post date appears as to be of 2005 :D.[...] Haha yeah, I'm not sure why Stefan replied to a post dating from 2005. T
Jan 08 2020