You have to do some refactoring on the C side first to make the C code usable 
from the C side. You can't just port some big C project directly to Nim in one 
go. What I would recommend is make the entry point in Nim as a first step. Like 
take the `main` function in C, rename it to `cMain` or whatever, and call that 
from Nim. Make sure that works.

After that you move functionality to Nim slowly.

You should also make sure that you can call Nim from C so that when you find a 
relatively self-contained module you can port that to Nim and expose it to C.

The call stack while porting will look like this:

  * `Nim entry point -> the actual C code doing the work`
  * `Nim entry point -> the actual C code doing most of the work -> self 
contained Nim modules exposed to C`
  * ... (you do whatever you can to reduce `the actual C code doing most of the 
work` part)



> the modules are too big...

This is not really a problem, you just have to know how to navigate the code.

> and depend of globals

This is not fun, but at first it's a good idea to just create a catch-all 
"context" struct and put all the globals in that. Then you pass that struct to 
each function. Depending on how you want to go about this, you can break that 
struct into smaller structs in C or just replicate the same thing in Nim and 
pass that to C functions.

> void functions

What's wrong with void functions? If you're talking about functions that don't 
return values but take in pointer for result argument, that's not a problem, 
just create a specific type that's only returned from that function and used by 
its callers. Don't fear more types, they're your friends at this points. Do as 
much as you can in types and reduce the code / pointers / whatever.

> hash tables, structs with function pointers

These are also not fun. What I recommend is move all hash table types, structs 
with function pointers etc. to their own module and make sure thay're only 
accessed through functions that you control. Nobody accesses them directly. 
Nobody.

So at first in Nim if you need to use those they're opaque types, you use them 
through the functions exposed from C. Same thing goes for the rest of the C 
codebase. You need to access a field of the struct? Create a 
`access_struct_field(struct*, result*)` function, and make sure only that is 
used everywhere. You need to create the struct? Make a `create_struct()` 
function that returns an opaque pointer. Nobody accesses the struct directly, 
only through the functions you provide.

You can even make it a seperate library with only needed functions exposed so 
that you can be sure.

Then when you're sure everyone accesses that stuff through functions you 
control, just swap those functions with Nim version! Easy peasy, lemon squeezy. 
I mean, not really, but you got the gist (by the way, I'm serious. NOBODY 
accesses those weird types directly until the whole codebase is in one language 
again).

Oh, and you can't use cool Nim features such as destructors while you have C 
code in the codebase, so you'll have to create `deinit` procs for you Nim types 
expose them. Call deinit in your destructor in Nim, and call the exposed deinit 
function in C.

Anyways, you'll have to be comfortable with C, I think that's pretty much clear 
by this point. Oh, and I'm not sure if I said this before but do not let weird 
types like type-specific-hash-tables and structs-with-function-pointers be 
accessed directly!

What I wrote above is not specific to Nim, I believe Nim has cool C 
interoperability features such as inlining C directly, but the points I made 
above goes for any porting project that will communicate over the C ABI.

Reply via email to