Hacker News new | past | comments | ask | show | jobs | submit | edsac_xyzw's comments login

This duct type is the Python native extension api (not python ctypes) which allows creating native code modules (aka libraries) in C or C++ and creating wrappers to existing C or C++ libraries. This escape hatch that enables offloading cpu-intensive computations to high performance libraries written in C, C++ or Fortran. Another benefit of python modules written in C or C++ is that they are not affected by the GIL (Global Interpreter Lock) problem, thus they can take advantage of multi-core and SIMD instructions and achieve higher performance.


Hardly it will fully replace C++ due to the pervasiveness of the language on many domains and also due to the C++ ecosystem that encompasses system programming; embedded systems; games and so on. For instance, the C++ ecosystem still outmatches rust regarding high performance libraries for several scientific computing domains; GUI graphical user interface libraries, such as Qt, MFC, wxWidget; Game engines and so on. In addition, Rust lacks openMP feature which allows parallelizing for-loops, which are widespread on scientific computing, for taking advantage of multi-core CPUs and from SIMD.


That is not too hard if one uses Pybind11 C++ library, which allows creating native code Python modules (shared libraries) in a simple and declarative manner. Other library that can be used with Pybind11 is Eigen for linear algebra that can perform loop fusion in numerical computation, for instance, it can add multiple vectors of same size in a single loop.


Matlab and its Simulink extension, which is widely used for designing control system has a feature for generating C code that can be deployed without Matlab runtime. Someone with knowledge of code generation and compilers could take this Matlab feature as an inspiration and implement a C code generator for Julia functions.

> Right now, it appears like a niche interpreted language for numeric geeks only.

Yes, it was designed for numerical and scientific computing. In Julia, you can at least prototype the numerical algorithm before implementing in C++ or Fortran.


Unlike Rust and Golang. C++ has long history and baggage, thus there is no standard tooling for C++ such as building systems and package managers. In the past, every operating system had its own set of preferred tooling for C and C++, on Linux and Unix-based system, lots of projects still use GNU autotools or Makefiles; on Windows, many projects still use the XML-based MSBUild from Visual Studio IDE. Many IDEs also have their own XML based building systems as well. Nowadays, CMake major IDEs support CMake and allows using CMakeLists.txt as a project file by just opening the directory containing this file. Some of those IDEs are Visual Studio IDE, Visual Studio Code, CLion, Eclipse (Via plugin), KDevelop and so on.

Regarding libraries dependencies, CMake has a FetchContent feature which allows downloading source code directly from http, ftp or git servers and adding this code as project dependency. This approach can avoid wasting time installing and configuring libraries. However, this technique is only feasible for lightweight libraries when the compile-time and library object-code size are not significant. For large libraries and frameworks where the compile-time is significant, such as Boost Libraries, Gtk or Qt, Conan or Vcpkg are the best solutions as they can cache and reuse library object-code with many other projects which reduces the compile-time and disk space usage.

C++ is not best solution for Web applications, in most cases you will not gain anything using C++ for this case, unless the web application is running in an embedded system such as router or a network printer. C++ is most suitable for cases where you need: high performance; access the operating system low level features; implement an operating system; implement an embedded system or a triple-A game.


If you use QEMU plus KVM (Kernel Virtual Machine), you can say goodbye to dual boot as the virtual machine is run with near native performance. For playing windows-only games, the solution is GPU passthrough, which allows allocating a GPU for the virtual machine providing the maximum gaming performance.


Does that work on all hardware? I've got laptops, and could maybe use hybrid graphics. I'll look into it, thanks!

Edit: so this doesn't work for muxless laptops (I've looked into it before and forgot). The discrete card runs through the Intel iGPU regardless if hybrid graphics is enabled or disabled.

The vBIOS can't be accessed directly, so it will result in an error. Some people got this working anyway, but it seems that it's unstable and/or results in low performance.


C++ could adopt the UFCS universal-function-call feature of D-language that allows any ordinary free function to be called as if they were methods, without any special kind of type annotation. One of major advantages of UFCS is that it enhances the discoverability of free functions in IDEs. An user could write 'Object' followed by dot '.' and the IDE could show all possible functions applicable to that type. In D-language, the UFCS also works for primitive types such as int, double and so on.

D-Language UFCS: http://ddili.org/ders/d.en/ufcs.html and https://tour.dlang.org/tour/en/gems/uniform-function-call-sy...


It also reduces the motivation to make "kitchen sink" classes. The idea is that functions that don't need access to private class members should not be member functions.


It could, but it keep getting rejected in committee votes, much to the frustration of Bjarne.


It's a shame. UFCS is one of the single biggest features that could really shave off huge amounts of boilerplate. It can also allow you to provide fine grained type safety where you may not usually be able to (as opposed to passing this down the chain a la operator<<)


> C++ could adopt the UFCS universal-function-call feature of D-language that allows any ordinary free function to be called as if they were methods, without any special kind of type annotation.

It really couldn't. It would be a breaking change.


what would it break? It litterally was proposed by an extension, with support from Stroustrup.

IIRC Stroustrup regrets using . for member function calls (as opposed to just some syntactic sugar for any function call)


The way it was worded in the GP comment would change name lookup in existing well-formed programs, making them fail to compile, or compile differently.

I'm not familiar with Stroustrup's proposal, but I doubt that he proposed it without some opt-in annotation.


Most embedded graphical Linux applications don't use X (X Windows System), instead they use framebuffer directly or any library such as Qt Widgets or QtQuick/Qml that draws on top of the framebuffer device file. So, there is no need for developing a new Window system that can work on both Desktop or embedded systems.


Well, most of QT libraries are LGPL, therefore you don't need a commercial license for a non open source project as long as you dynamic link against the Qt library and don't static link against it. On Windows it is easy to pack an application with all shared library dependencies, all you need is copying the shared libraries (*.dll files) to the executable directory. Unlike on Unixes, on Windows, the loader searches first the dependencies at the executable current directory or in directories listed in PATH variable.

Other alternatives are: WxWidgets; MFC - Microsft Foundation Classes that has GUI builder in Visual Studio IDE; Borland VCL - Visual Component Library; Sciter library which allows creating the GUI in html and has a C API. Another way is to build the application on top of Win32 GUI API that is well documented and has lots of examples, unlike X11-Xorg (X Windows System) used on Unixies, such as Linux distributions or BSD variants.


Those large amount bindings are possible due to the GTK be written in C, which allows creating binding to GTK via FFI - foreign function interface or native interface (borrowing the term from java JNI).

Creating bindings to QT is harder because Qt is written in C++ and C++ compilers does not have a standard ABI and FFIs foreign function interfaces can only load C-compatible functions and types. Another challenge is that older Qt (< Qt5) versions relied too much on MOC - Meta Object Compiler for reflection and callbacks.

The workaround for calling a C++ libraries from other languages is to create a C-API for the C++ library via 'extern "C"' wrappers with opaque pointers. Qt could be used by many other programming languages if it was shipped with an official C-API or interface as previously mentioned.

I a have a proof-of-concept code of a C-API for Qt5 Widgets and three client codes in C, D-language and Julia language which call the C wrapper library and build Qt5-Widgets user interfaces. This code is available at: https://caiorss.github.io/C-Cpp-Notes/CwrapperToQtLibrary.ht...

Another way to generate bindings to C++ libraries is by using SWIG that parses the C++ code generates native interface bindings.


The fact C++ has no stable ABI is not what stops you from creating language bindings, because you need that kind of interoperability only for those symbols that need to cross the FFI. It's more about how the library is designed than the implementation language itself; for instance, Tensorflow is mostly written in C++, but its intended use is as a Python module. Also, by using GLib you take in so many GLib-specific types and assumptions it becomes extremely wonky using it from non-GLib code, and you often end up writing some kind of FFI anyway in order to wrap its behaviour. I've even seen some libraries ship both a C and a GLib wrapper, as if it was almost like a separate language.

LLVM is a good example of C++ being able to interface with other languages using its C FFI, being completely written in C++ but having bindings for almost every programming language. I can count among them at least C, C++, D, Rust, OCaml and Python, for instance, and while it has an "LLVM-C" library available, you are not necessarily forced to use it; you can just export what you need directly from C++ using a file with a few functions defined as extern "C".

Rust is probably even trickier to interface with C but it's still pretty doable, given that GNOME is now rewriting several components in Rust (see librsvg).

I still think one of the main reasons C++ was discarded so quickly at the time, despite Qt and KDE being older than GNOME and in C++ already, was being born from a culture that had at the time already rejected the adoption of C++.

GNU has historically always discouraged its projects, especially those they cared about the most, from using C++. It's well documented how strongly RMS despised the language and how he actively pushed people towards using C for such tasks. I think it's still written in somewhere in the GNU website, even.

Heck the GCC developers had to ask RMS the permission to switch to C++ a few years ago, due to GCC becoming harder and harder to maintain. Ironically, it used internally its own private C implementation of dynamic vectors, while being one of the main implementers of the STL. I think it even had some sort of garbage collection inside, and that they largely reimplemented an object system too using C and macros (it's been a while since I read the GCC sources, so my memories could be incorrect). RMS wasn't really that happy about it, but it grumpily said they could.


The lack of standard ABI makes harder to call C++ from foreign-function interfaces or from dlopen/LoadLibrary dynamic loading functions. It lack of ABI also does not allow linking against object-codes built by the other compilers or even older versions of the same compiler.

In C, a symbol name matches the function name, if you have a function called 'void my_function()', the symbol will be 'my_function' and you will be able to load this function from a foreign function interface as libffi.load('my_function', ... types ...). The trouble with C++ bindings is that symbols are mangled, the function names are encoded, a function named 'Workaround1::get_callback()::callback' can be encoded (mangled) as _ZZN11Workaround112get_callbackEvE8callback - this encoding is specific to a given compiler ABI, in addition FFIs cannot load non-C types.

Tensorflow uses the hourglass design pattern, this library is implemented internally in C++, but does not exposes a C++ API, instead it exposes a C wrapper built with 'extern "C" and opaque pointers (void* pointers or incomplete types). This approach allows the library to be used in the same way as a C library and makes easier to call the library via FFI. Another benefit is the better binary compatibility as object-codes built with other compilers canlink against Tensorflow without any issues. Another library that uses this approach is the Squirrel embedded scripting language, that is implemented in C++, but only exposes a C API. So, this technique allows a C++ library to be used as C library and makes possible calling it through FFI.

I guess that in the case of LLVM it may also use this pattern of using C++ internally and only exposing a C API via extern "C". The disadvantage of this pattern is the need of lots cumbersome extern "C" wrappers for every member function of a class and for all exposed classes. LibClang LLVM may be helpful for automating the generation of this C wrapper code.


Objective-C might not use the C ABI, but you can certainly interact with it in a stable way (with no code modifications) entirely in C.


Consider applying for YC's first-ever Fall batch! Applications are open till Aug 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: