Thread overview
Using D within a rust codebase
Jul 26, 2020
powerboat9
Jul 27, 2020
Paul Backus
Jul 27, 2020
Jacob Carlborg
Jul 27, 2020
Ali Çehreli
Jul 27, 2020
Ali Çehreli
Jul 28, 2020
Jacob Carlborg
July 26, 2020
I have an existing rust project, and I'm trying to rewrite part of it in D. However, I'm not sure how to get rust -> dlang interop working. I've looked into rust -> c -> dlang interop, but I'm not sure how to get c -> dlang interop working either.
July 27, 2020
On Sunday, 26 July 2020 at 21:18:19 UTC, powerboat9 wrote:
> I have an existing rust project, and I'm trying to rewrite part of it in D. However, I'm not sure how to get rust -> dlang interop working. I've looked into rust -> c -> dlang interop, but I'm not sure how to get c -> dlang interop working either.

Here's the basic approach:

1. Write an `extern(C)` function in D.
2. Write a corresponding declaration of that function in C (typically, in a header file).
3. Use your D and C compilers to separately compile your D and C source files, respectively.
4. Use your D compiler to link the resulting object files.

For example, given these source files:

--- lib.d
extern(C) void hello()
{
	import std.stdio: writeln;
	writeln("Hello from D!");
}

--- lib.h
void hello();

--- main.c
#include "lib.h"

void main()
{
	hello();
}

...you can compile them with the following commands:

$ dmd -c lib.d     # produces lib.o
$ gcc -c main.c    # produces main.o
$ dmd main.o lib.o # produces main

You should now be able run `./main` and see it print "Hello from D!"
July 27, 2020
On 2020-07-27 03:03, Paul Backus wrote:

> extern(C) void hello()
> {
>      import std.stdio: writeln;
>      writeln("Hello from D!");
> }

The D runtime needs to be initialized first [1]. Then it should be terminated as well [2].

[1] https://dlang.org/phobos/core_runtime.html#.rt_init
[2] https://dlang.org/phobos/core_runtime.html#.rt_term

-- 
/Jacob Carlborg
July 27, 2020
On 7/27/20 3:50 AM, Jacob Carlborg wrote:> On 2020-07-27 03:03, Paul Backus wrote:
>
>> extern(C) void hello()
>> {
>>      import std.stdio: writeln;
>>      writeln("Hello from D!");
>> }
>
> The D runtime needs to be initialized first [1]. Then it should be
> terminated as well [2].
>
> [1] https://dlang.org/phobos/core_runtime.html#.rt_init
> [2] https://dlang.org/phobos/core_runtime.html#.rt_term
>

They should be taken care of when the program is linked with a D compiler.

Otherwise, e.g. when the extern(C) code is part of a library written in D, one way of doing it is to add the following two functions to the library. (Typing by hand; may have typos).

import core.runtime;

pragma (crt_constructor)
extern (C)
int lib_init() {
  return Runtime.initialize() ? 0 : 1;
}

pragma (crt_destructor)
extern (C)
int lib_deinit() {
  return Runtime.terminate() ? 0 : 1;
}

Ali

July 27, 2020
On 7/27/20 4:43 AM, Ali Çehreli wrote:
> On 7/27/20 3:50 AM, Jacob Carlborg wrote:> On 2020-07-27 03:03, Paul 

>  > The D runtime needs to be initialized first [1]. Then it should be
>  > terminated as well [2].
>  >
>  > [1] https://dlang.org/phobos/core_runtime.html#.rt_init

[...]

> pragma (crt_constructor)
> extern (C)
> int lib_init() {
>    return Runtime.initialize() ? 0 : 1;
> }

Ok, now I learned that my bool-to-int conversion is already taken care of by rt_init(). Cool. :)

Ali

July 28, 2020
On 2020-07-27 13:43, Ali Çehreli wrote:

> They should be taken care of when the program is linked with a D compiler.

Just linking with a D compiler is not sufficient. There needs to be a D main function for the runtime to automatically be initialized. If you make the D code a bit more complicated, for example:

static this()
{
    import std.stdio: writeln;
    writeln("static this");
}

Then that won't be printed without a D main function or manually initializing the runtime.

The initial question was about linking D code into an already existing Rust code base. I don't think the first thing to try is to replace the Rust main function with a D main function.

-- 
/Jacob Carlborg