www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Tuts/Aritcles: Incrementasl C++-to-D conversion?

reply "Nick Sabalausky (Abscissa)" <SeeWebsiteToContactMe semitwist.com> writes:
Are there any tutorials or articles out there for "getting started with 
converting a C++ codebase to D one module at a time?" Or at the very 
least: tips, tricks, lessions learned, from those who have come before.
Feb 21 2018
next sibling parent Mike Franklin <slavo5150 yahoo.com> writes:
On Thursday, 22 February 2018 at 04:16:44 UTC, Nick Sabalausky 
(Abscissa) wrote:
 Are there any tutorials or articles out there for "getting 
 started with converting a C++ codebase to D one module at a 
 time?" Or at the very least: tips, tricks, lessions learned, 
 from those who have come before.
These are the resources I'm aware of: https://dlang.org/articles/cpptod.html https://wiki.dlang.org/Programming_in_D_for_C%2B%2B_Programmers Mike
Feb 21 2018
prev sibling next sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
Nick Sabalausky (Abscissa) wrote:

 Are there any tutorials or articles out there for "getting started with 
 converting a C++ codebase to D one module at a time?" Or at the very 
 least: tips, tricks, lessions learned, from those who have come before.
from my experience (various codebases up to middle size, mostly C, some C++): fsck the "one module at a time" idea! even in D modules are interwined, and in C and C++ they're even more so. besides, converting tests is tedious, it is much funnier to have something working. so, i'm usually converting alot of code, up to the whole codebase. it is not fun when compler spits 100500 errors, but when it finally stops... oh, joy! trick: use 'sed' (or your favorite regexp search-and-replace tool) alot. basically, before HDD crash i almost had a set of scripts that does 80-90 percents of work translating C to D with sed. ;-) then use editor with "jump to error line" support, and simply compile your code, fixing errors one by one. tip: try to not rewrite code in any way until it works. i know how tempting it to replace "just this tiny thing, it is so ugly, and in D we have a nice idiom!" NEVAR. this is by far the most important thing to remember (at least for me), so i'll repeat it again: no code modifications until it works! personal memories: C code often using things like `a == &arr[idx]`, where idx can go just past the last array element. it got me when i was doing enet conversion. nasty trick. otherwise, sweat and blood, and patience.
Feb 22 2018
next sibling parent Timothee Cour <thelastmammoth gmail.com> writes:
also related: https://github.com/Syniurge/Calypso/issues/85
(feasibility of extending calypso to do source to source translation
(eg C++ => D or C=>D) )


On Thu, Feb 22, 2018 at 12:43 AM, ketmar via Digitalmars-d-learn
<digitalmars-d-learn puremagic.com> wrote:
 Nick Sabalausky (Abscissa) wrote:

 Are there any tutorials or articles out there for "getting started with
 converting a C++ codebase to D one module at a time?" Or at the very least:
 tips, tricks, lessions learned, from those who have come before.
from my experience (various codebases up to middle size, mostly C, some C++): fsck the "one module at a time" idea! even in D modules are interwined, and in C and C++ they're even more so. besides, converting tests is tedious, it is much funnier to have something working. so, i'm usually converting alot of code, up to the whole codebase. it is not fun when compler spits 100500 errors, but when it finally stops... oh, joy! trick: use 'sed' (or your favorite regexp search-and-replace tool) alot. basically, before HDD crash i almost had a set of scripts that does 80-90 percents of work translating C to D with sed. ;-) then use editor with "jump to error line" support, and simply compile your code, fixing errors one by one. tip: try to not rewrite code in any way until it works. i know how tempting it to replace "just this tiny thing, it is so ugly, and in D we have a nice idiom!" NEVAR. this is by far the most important thing to remember (at least for me), so i'll repeat it again: no code modifications until it works! personal memories: C code often using things like `a == &arr[idx]`, where idx can go just past the last array element. it got me when i was doing enet conversion. nasty trick. otherwise, sweat and blood, and patience.
Feb 22 2018
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Feb 22, 2018 at 10:43:24AM +0200, ketmar via Digitalmars-d-learn wrote:
 Nick Sabalausky (Abscissa) wrote:
 
 Are there any tutorials or articles out there for "getting started
 with converting a C++ codebase to D one module at a time?" Or at the
 very least: tips, tricks, lessions learned, from those who have come
 before.
from my experience (various codebases up to middle size, mostly C, some C++): fsck the "one module at a time" idea! even in D modules are interwined, and in C and C++ they're even more so. besides, converting tests is tedious, it is much funnier to have something working.
I'm in the middle of the process of converting an old C++ project right now (it's so old that most of it dates back to C++98, and needs to be compiled with options to suppress C++11 deprecations and errors). I started out with the idea of incremental conversion, and managed to get as far as converting main() to D via shims to transition between the D/C++ boundary. The straw that broke the camel's back, though: C++ exceptions that need to percolate all the way to the top-level. I know people have mentioned Calypso, etc., but I'm mainly using dmd right now, and I really don't like the idea of putting a bunch of effort into using a different toolchain just to be able to incrementally migrate a lousy C++ project. So I'm starting to agree with ketmar: just jump into D cold turkey and convert the whole dang thing in one go. Actually, what I ended up doing right now is no longer converting, but rewriting individual modules in D. It's more effort, but I'm aiming for more idiomatic D code, and also the whole reason I started out on this task is because I want to refactor the code to fix some fundamental design flaws, but I really do not want to work with C++ anymore. So it doesn't make sense to me to struggle with making C++ code compile in D, only to immediately afterwards rewrite it anyway. Why not rewrite it right now, using the C++ code as a reference rather than a direct source. [...]
 tip: try to not rewrite code in any way until it works. i know how
 tempting it to replace "just this tiny thing, it is so ugly, and in D
 we have a nice idiom!" NEVAR. this is by far the most important thing
 to remember (at least for me), so i'll repeat it again: no code
 modifications until it works!
So I'm taking the wrong approach, perhaps. :-D But basically, I'm starting out with the leaf node modules and rewriting it in D, complete with unittests and what-not, to ensure it's semantically correct. Perhaps when I get to the main code I may have to compromise on my rewrite approach, because it will be too big to rewrite in one go. But we'll see. One thing that's *really* helping is D's built-in unittests. With this approach, I can actually just comment out the C++ code, then gradually uncomment individual functions one at a time, translate to D, then add unittests to make sure it works correctly. This is extremely helpful because I don't need to have a working main() to test individual translated functions -- that wouldn't work because too many things depend on too many other things, so requiring a functional main() means rewriting the entire codebase before you get something that's testable. There's just too much room for human error there. Being able to translate C++ functions one at a time and have unittests to ensure I didn't introduce any bugs, is a HUGE help. It helps build confidence that I'm actually making progress (instead of writing a huge amount of code that ultimately doesn't work!). [...]
 otherwise, sweat and blood, and patience.
+1. Yep, it's a lot of work. But I'm chugging away at it. Can't wait till the thing is finally running in D, and I can kill off the old C++ sources forever. Just too much unmaintainable ugliness there that I'd rather not remember. T -- "I'm not childish; I'm just in touch with the child within!" - RL
Feb 22 2018
prev sibling parent biocyberman <biocyberman gmail.com> writes:
On Thursday, 22 February 2018 at 08:43:24 UTC, ketmar wrote:
 Nick Sabalausky (Abscissa) wrote:

 [...]
from my experience (various codebases up to middle size, mostly C, some C++): fsck the "one module at a time" idea! even in D modules are interwined, and in C and C++ they're even more so. besides, converting tests is tedious, it is much funnier to have something working. so, i'm usually converting alot of code, up to the whole codebase. it is not fun when compler spits 100500 errors, but when it finally stops... oh, joy! trick: use 'sed' (or your favorite regexp search-and-replace tool) alot. basically, before HDD crash i almost had a set of scripts that does 80-90 percents of work translating C to D with sed. ;-) then use editor with "jump to error line" support, and simply compile your code, fixing errors one by one. tip: try to not rewrite code in any way until it works. i know how tempting it to replace "just this tiny thing, it is so ugly, and in D we have a nice idiom!" NEVAR. this is by far the most important thing to remember (at least for me), so i'll repeat it again: no code modifications until it works! personal memories: C code often using things like `a == &arr[idx]`, where idx can go just past the last array element. it got me when i was doing enet conversion. nasty trick. otherwise, sweat and blood, and patience.
These are good starting point so we don't get lost in the process. Still not much exprience doing, but I think these pieces of advice are especially true if the codebase is big or complicated, making it difficult to understand what the C/C++ is doing. When we don't understand the code, re-writing from scratch is not possible.
Feb 23 2018
prev sibling next sibling parent Kagamin <spam here.lot> writes:
On Thursday, 22 February 2018 at 04:16:44 UTC, Nick Sabalausky 
(Abscissa) wrote:
 Are there any tutorials or articles out there for "getting 
 started with converting a C++ codebase to D one module at a 
 time?" Or at the very least: tips, tricks, lessions learned, 
 from those who have come before.
AFAIK, visuald has a tool that just translated C++ to D https://github.com/dlang/visuald/tree/master/c2d
Feb 23 2018
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Feb 21, 2018 at 11:16:44PM -0500, Nick Sabalausky (Abscissa) via
Digitalmars-d-learn wrote:
 Are there any tutorials or articles out there for "getting started
 with converting a C++ codebase to D one module at a time?" Or at the
 very least: tips, tricks, lessions learned, from those who have come
 before.
Here's a really nasty thing that I just came across today (cf. other thread as well), in translating C++ code that calls an external library via a C API: // C (called from original C++ code): typedef double mytype[1]; struct blah { mytype x; } void foo(mytype x); void bar(struct blah b); A na´ve translation to D would be: // D (incorrect) alias mytype = double[1]; struct blah { mytype x; } void foo(mytype x); // Uh oh void bar(struct blah b); The problem is that in C, a function parameter declared as double[1] is actually the same as double* because of C's infamous array -> pointer degradation. So the parameter of foo should actually be declared as double*, not as double[1] (via the `mytype` alias). However, simply changing the definition of `mytype` to `double*` leads to another problem: the definition of struct blah will be wrong, because in C, a struct field declared as double[n] is actually equivalent to a D static array, i.e., it occupies the space of n doubles. Changing that to double* makes the D declaration of the struct incorrect. Furthermore, calling foo from D now requires explicitly writing `&x` instead of merely `x`. The solution I eventually settled on is to adopt the convention that whenever a C "static array" appears as a function parameter, declare it as `ref`. So: // D (correct) alias mytype = double[1]; struct blah { mytype x; } void foo(ref mytype x); // N.B.: add `ref` here void bar(struct blah b); This allows correct matching to the C API without requiring inserting `&`s everywhere. T -- What's an anagram of "BANACH-TARSKI"? BANACH-TARSKI BANACH-TARSKI.
Feb 26 2018