将庞大的C ++库自动包装到C中,以便在Swift / Go中导入

Let's say i have a huge lib in C++ (with tons of dependencies, it needs about 3h for a full build under GCC). I want to build upon that lib but don't want to do so in C++ but rather in a more productive language. How can i actually bridge or wrap that extern lib package so i can access it in another language and program on top of it?

Languages considered:

  • Swift
  • Go

What i found is, that both languages do provide auto bridging or wrapping for C libs and code (I don't actually know whats the difference between wrapping / bridging). So, if i have some c code, i can just throw it in the same Swift or Go project and can use it with a simple import in my project.

This doesn't work in both languages for C++ code however. So i googled how to transform C++ libs to C code or generate autowrappers. I found the following:

  1. swig.org - auto wrapper for C++ libs
  2. Comeau C++ compiler - automatically transfers C++ to C code
  3. LLVM - should be able to take any input and transform it to any output that LLVM is capable of.

Question:

  1. Is it even in the realms of usable / realistic / managable to build on top of such a huge lib in other languages like Swift / Go, if using auto wrapping or auto bridging?
  2. What of the 3 listed libs / programs / frameworks works best for the process of C++ -> C (because Swift and Go both provide C auto wrapping).
  3. Are there better alternatives than what i considered so far?
  4. Would it be better to just "stick with C++" as using any other tools to do the wrapping / bridging process would be far to much work to equal out the benefit of using a more productive language like Swift / Go?

Thanks:)

Disclaimer: There is also the possibility to manually wrap a C++ lib in C but that would take an unbearable amount of work for such a huge lib.

Q1: Is it realistic?

Not realistic, because any large complicated C++ interop is going to get too complicated. Automatic tools are likely to fail and manual work is too hard.

Q2: What's best?

I don't know and given A1 it does not seem to matter.

Q3: Alternative? Q4: Is C++ only the best alternative?

If you want to take advantage of existing C++ code from another language regardless of the language involved the best option in complex scenarios is to use a hybrid approach.

Most languages provide interop to C and not C++ due to non-standard C++ naming convention. In other words, just about every language provides access to plain C-functions, but C++ is frequently not supported.

Since your library is complex, the best solution would be based on "Facade" pattern. Create a new C-library and implement application specific logic that utilizes C++ library. Try to design this library to be as thin as possible. The goal is not to write all business logic, but to provide C-functions that hold on C++ objects and call C++ functions. The GO-level language code would then call this library to use C++ library underneath. This approach differs from Q1 approach. In Q1 you attempt to have one interop call on per C++ function or object's method. In Facade you attempt to implement C++ usage scenarios that are unique to your application.

With Facade you reduce the scope of interop work, because you target your application scenarios. At the same time you mitigate away from C++ complexity at GO language level.

For example, you need to read a temperature sensor using C++ library.

In C++ you'd have to do:

  1. open file
  2. read stream until you find SLIP terminator
  3. read one "record"
  4. close file

With facade you create a single function called "readTemperature(deviceFileName)" and that C function executes 4 calls at once.

That's a fake example, just to show the point.

With facade you might want to hide original C++ objects and at this point it becomes a small layer. The goal here is to stay focused and balance your application needs with generalization to support your application.

Interestingly enough Facade approach is a way to improve interop performance. Interop in just about every language is more expensive than normal operations due to need to marshal from langauage runtime environment and keep it protected. Lots of interop calls slow down application (we are talking about millions here). For example, having 10 interop calls combined into 1 improves performance, because amount of itnerop operations is reduced.