www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - ctod: a tool that translates C code to D

reply Dennis <dkorpel gmail.com> writes:

**GitHub:** https://github.com/dkorpel/ctod
**Dub:** https://code.dlang.org/packages/ctod

---

In the summer of 2020, before ImportC, I wrote a tool to help me 
with my D translations of C libraries: 
[glfw-d](https://code.dlang.org/packages/glfw-d) and 
[libsoundio-d](https://code.dlang.org/packages/libsoundio-d). I 
wanted to publish it at some point but kind of forgot about it, 
until [Steven Schveighoffer asked about 
it](https://github.com/dkorpel/glfw-d/discussions/18) last week 
for his [D translation of 
raylib](https://github.com/schveiguy/draylib). That made me 
inspired to work on it again, and I finally fixed the Windows 
build, so I want to share it now.

It uses 
[tree-sitter-c](https://github.com/tree-sitter/tree-sitter-c) to 
parse .c or .h files including preprocessor directives, and then 
replaces C syntax patterns with roughly equivalent D patterns 
wherever it needs and can. Because tree-sitter is very good at 
error-recovery, it will always output a best-effort translated .d 
file, no matter the content of the .c file.

Example input file main.c:
```C
#include <stdio.h>

#define TAU 6.283185307179586476925

int main(void) {
     char buf[32];
     sprintf(buf, "tau = %f\n", TAU);
     Wait, this line is not C syntax 🤔
     return 0;
}
```

Output main.d:
```D
module main;
 nogc nothrow:
extern(C): __gshared:

public import core.stdc.stdio;

enum TAU = 6.283185307179586476925;

int main() {
     char[32] buf;
     sprintf(buf.ptr, "tau = %f\n", TAU);
     Wait, this_ line is_; not C syntax 🤔
     return 0;
}
```


The output is supposed to be a good starting point for manual 
translation: tedious syntax changes are done for you, but you're 
left with the task of translating (non-trivial) macros, fixing 
errors because of D's stricter type system, and other misc things 
ctod doesn't translate properly yet (see also [issues on 
GitHub](https://github.com/dkorpel/ctod/issues) 🙂).

With the rise of ImportC the use cases for this tool decrease, 
but in case you still find yourself translating C to D, I hope 
this is of use to you!
Oct 13 2022
next sibling parent Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Thursday, 13 October 2022 at 19:18:07 UTC, Dennis wrote:

 **GitHub:** https://github.com/dkorpel/ctod
 **Dub:** https://code.dlang.org/packages/ctod

 [...]
Looks like it could be a nice addition to the toolbox
Oct 13 2022
prev sibling next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 10/13/22 3:18 PM, Dennis wrote:

 The output is supposed to be a good starting point for manual 
 translation: tedious syntax changes are done for you, but you're left 
 with the task of translating (non-trivial) macros, fixing errors because 
 of D's stricter type system, and other misc things ctod doesn't 
 translate properly yet (see also [issues on 
 GitHub](https://github.com/dkorpel/ctod/issues) 🙂).
I want to say, this has been incredibly useful to me! I spent many hours translating one file in raylib, which was about 6000 lines (it's still not completely finished, but only because I'm not currently supporting WASM). Dealing with all the rote tedious issues was the biggest pain. There are tens of thousands of lines of code left to translate, and most of them reside in header-only libraries that raylib sniped from other projects (seen in the "external" directory). In a few hours time, with ctod, I've already translated 3 of these files, and the result means less requirements for C building. My original plan was to just leave the internal stuff as C since it's only used internally for raylib (e.g. audio file reading, compression, etc.). I was going to actually ship binary libraries of the internal C stuff for various architectures so you could just use dub. But now with this tool, I think we have a shot of making a complete port, so no external tools or dependencies are needed!
 With the rise of ImportC the use cases for this tool decrease, but in 
 case you still find yourself translating C to D, I hope this is of use 
 to you!
I want to say something about this. ImportC is great if you want to use an existing library. But it still means you are using a C library. e.g. raylib uses null-terminated strings for all text processing. It uses malloc/free for memory management (and it is actually pretty full of buffer overflow possibilities, as a typical C project might be). Not to mention the lack of overloads... With ImportC I might be able to just use raylib with it's current C API. But with ctod, I can build upon raylib to make a D library that is even more fun and intuitive to use. Thanks Dennis! -Steve
Oct 13 2022
prev sibling next sibling parent ryuukk_ <ryuukk.dev gmail.com> writes:
WOW that's pretty cool!!

It was always time consuming having to manually port C code, your 
tool will be very helpful!

Thanks a lot for sharing!
Oct 13 2022
prev sibling parent stew <estewh gmail.com> writes:
On Thursday, 13 October 2022 at 19:18:07 UTC, Dennis wrote:

 **GitHub:** https://github.com/dkorpel/ctod
 **Dub:** https://code.dlang.org/packages/ctod

 ---

 In the summer of 2020, before ImportC, I wrote a tool to help 
 me with my D translations of C libraries: 
 [glfw-d](https://code.dlang.org/packages/glfw-d) and 
 [libsoundio-d](https://code.dlang.org/packages/libsoundio-d). I 
 wanted to publish it at some point but kind of forgot about it, 
 until [Steven Schveighoffer asked about 
 it](https://github.com/dkorpel/glfw-d/discussions/18) last week 
 for his [D translation of 
 raylib](https://github.com/schveiguy/draylib). That made me 
 inspired to work on it again, and I finally fixed the Windows 
 build, so I want to share it now.

 It uses 
 [tree-sitter-c](https://github.com/tree-sitter/tree-sitter-c) 
 to parse .c or .h files including preprocessor directives, and 
 then replaces C syntax patterns with roughly equivalent D 
 patterns wherever it needs and can. Because tree-sitter is very 
 good at error-recovery, it will always output a best-effort 
 translated .d file, no matter the content of the .c file.

 Example input file main.c:
 ```C
 #include <stdio.h>

 #define TAU 6.283185307179586476925

 int main(void) {
     char buf[32];
     sprintf(buf, "tau = %f\n", TAU);
     Wait, this line is not C syntax 🤔
     return 0;
 }
 ```

 Output main.d:
 ```D
 module main;
  nogc nothrow:
 extern(C): __gshared:

 public import core.stdc.stdio;

 enum TAU = 6.283185307179586476925;

 int main() {
     char[32] buf;
     sprintf(buf.ptr, "tau = %f\n", TAU);
     Wait, this_ line is_; not C syntax 🤔
     return 0;
 }
 ```


 The output is supposed to be a good starting point for manual 
 translation: tedious syntax changes are done for you, but 
 you're left with the task of translating (non-trivial) macros, 
 fixing errors because of D's stricter type system, and other 
 misc things ctod doesn't translate properly yet (see also 
 [issues on GitHub](https://github.com/dkorpel/ctod/issues) 🙂).

 With the rise of ImportC the use cases for this tool decrease, 
 but in case you still find yourself translating C to D, I hope 
 this is of use to you!
This is cool, I once did a port of DWM (tiling X window manager) to D because I like DWM, I wanted to learn D from within a code base I knew reasonably well and I wanted a pure D window manager, why not? It was quite tedious though and DWM is pretty clean concise C code. As an experiment I just did it again with this tool to try it out and it was fantastic. For that small code base it only took about 15min to port and get compiling and a few more to fix the two minor runtime issues. Without this tool it took several hours to get compiling and then several more to nail down and fix all the runtime bugs. Thanks!
Oct 14 2022