Hello there, fellow programmers! I am an Aeronautical Engineering student who is doing research on Multidisciplinary Optimization (MDO) since the beginning of this year.
All the code I’ve written so far is in Python, but I want to move it to C so I can learn more about low level programming and so I can have more control over what my code actually does (since it is an MDO code, it needs to be very optimized because every 0.5 seconds added to each iteration add 500 seconds over 1000 iterations (9 minutes!)). I am taking an online course on C from edX, but I still cannot understand how to actually substitute objects for C compliant code. The main problem is that my original code uses lots of objects, and I simply do not know how to eliminate objects from my code.
Can someone help me? Any help is welcomed.
[edit] Thanks for all your answers, I think I’m getting it now.
If your goal is to rewrite your python code in C with minimal hassle, start thinking of objects as structs with functions attached to them. If you detach the functions from the structs, instead having them take structs as an argument, then you can obtain something which is C-like but likely very unoptimised.
Personally, I think I would steer you towards Rust or C++ instead - both can run just as quickly, but have more OOP features and modern features which may make moving easier. Learning C is still a very good thing to do, but I’m not sure this project would be the best project to do that with.
I second everything said here. I would add that C++ might be a better candidate in this case as translating Python’s OOP and Context Management would be more easily done in C++ than rust IMO. Thought it might involve a bit of template if your code heavily rely on duck typing, and you will have to get familiar with the weird move semantic of C++. Also make sure to activate ASAN and maybe UBSAN for the development phase and have an optimized build with debug symbols to run with valgrind (this is also valid if you decide to stick with C).
But if you’re already familiar in rust, pick that.
Unless you have specific platform requirements, I would avoid C for any large projects nowadays. It’s OK when learning low level stuff because it’s one of the languages with the fewest abstraction layers, but this aspect becomes a weakness at scale. And especially when porting from higher level languages.
Also, something not mentioned yet, do you actually need to move everything to C? It might be that the core of the logic is only a few function that you can more easily translate to C and then call from ctypes or a native module. So you get to discover C for 80% of the benefits and 20% of the hassle.
The main reason why one would want to use C is likely Foreign Function Interface (FFI), whatever code you write in C (apart from emitting assemblies) would likely be usable and extensible from any other programming languages so long that some of the conventions are followed. Rust and C++ could likely produce code just as fast as well optimized C code, but inaccessible or not readily accessible to other programming languages IE Name Mangling that are compiler implementation dependent, missing FFI access to STL and Traits and so forth. If it was readily accessible, then I would ask where is QT API access for any other programming language.
FFI is pretty much the only reason why I am still writing in C in a very large project like GUI Toolkit to replace GTK and QT by using Vulkan. I would not recommend doing what I do when it come to implementing OOP manually in C to ensure that other programming language could extend my library. (I would write VTable manually and establish some of the OOP paradigms. C compiler does extremely well when optimizing out virtual dispatches to static dispatch.)
That’s about it, as you said, it have a lot of hassles in C, so that why I am now working on Compiler Generator to create dialects on top of C similarly to MLIR so it would compile to readable C at the end of it as well as generating LSP server, FFI-JSON, and other things for it.
Deep down, C++ class functions take a pointer to their objects as a first “invisible” parameter.