Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
May 26, 2005 Calling D code from C | ||||
---|---|---|---|---|
| ||||
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 Re: Calling D code from C | ||||
---|---|---|---|---|
| ||||
Posted in reply to Niko Korhonen | 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 27, 2005 Re: Calling D code from C | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vathix | 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.
|
January 08, 2020 Re: Calling D code from C | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vathix | 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().
|
January 08, 2020 Re: Calling D code from C | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stefan | 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. |
January 08, 2020 Re: Calling D code from C | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | 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: [...]
>> 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
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.
|
January 08, 2020 Re: Calling D code from C | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ferhat Kurtulmuş | 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. |
January 08, 2020 Re: Calling D code from C | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | 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: [...]
>> 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
Google is good at resurrection.
|
Copyright © 1999-2021 by the D Language Foundation