24

I have a program which is configured by the user by using C++ classes and the same class should be used to configure a program which can only use a subset of C99 (Open CL Language).

So my question is: Is there a way to compile C++ to C-Code?

Open Source would be great!

cl_progger
  • 405
  • 2
  • 5
  • 10
  • 1
    possible duplicate of [C++ to C conversion](http://stackoverflow.com/questions/3706561/c-to-c-conversion) – Kirill V. Lyadvinsky Feb 19 '11 at 10:59
  • 14
    lovely saying that this is a duplicate of a question that was closed as not a real question... – 6502 Feb 19 '11 at 11:06
  • Also beware that there's a difference between converting a snippet like a single class, and compiling a whole C++ program with C source as the target. Some of the tools mentioned in the answers below won't give you a way to actually *call* your configuration class (written in C++ and converted to possibly-unreadable C) from your C program, or at least not to do so easily. If the process exports the C++ functions at all then they will have mangled names, as the first obstacle. – Steve Jessop Feb 19 '11 at 13:19
  • 5
    The usual way to make some C++ code callable from your C code *isn't* to convert it to C. Instead you put a wrapper API around the C++ code, consisting of `extern "C"` functions, then you compile it with a C++ compiler that produces object files compatible with the same linker used by your C compiler, and link everything together. Conversion would be a last resort if your platform doesn't provide compatible C and C++ compilers (most likely reason I suppose being that it doesn't provide a C++ compiler/runtime at all). – Steve Jessop Feb 19 '11 at 13:24
  • In case of my problem, I am merely dealing with simple classes without inheritance and I am working with Open CL C plattform [link](http://www.khronos.org/opencl/) which is thought for graphics cards and so on and I don't get a C++ compiler. My problem is that CUDA supports C++ partly and my program shall complete a software sweet so that it would be great to specify the source as c++ class instead of doing twice the work which would be error-prone. – cl_progger Feb 19 '11 at 20:03
  • possible duplicate of [C++ frontend only compiler (convert C++ to C).](http://stackoverflow.com/questions/1833484/c-frontend-only-compiler-convert-c-to-c) – Fred Nurk May 06 '11 at 03:17
  • possible duplicate of [How to convert C++ Code to C](http://stackoverflow.com/questions/737257/how-to-convert-c-code-to-c) – Anderson Green Jul 04 '14 at 18:43
  • OpenCL 2.2 now supports C++ kernels. https://www.khronos.org/news/press/khronos-releases-opencl-2.2-provisional-spec-opencl-c-kernel-language – Lena Apr 19 '16 at 15:51

5 Answers5

21

You could use the clang C++ frontend to generate llvm bytecode, and use llc to emit C code, see llc doc, especially the c option. Both are open source, with BSD like licenses.

tonio
  • 9,747
  • 1
  • 42
  • 54
  • 3
    If the resulting code doesn't need to do anything except build, this migh be the best choice. Don't expect `llc`'s output to be anywhere readable code. – rubenvb Feb 19 '11 at 12:31
  • Yeah. Very readable ^^. I think for my purpose the code would be too fat. The software is to going to run on a graphics card later (language Open CL C) and everyone wants to have small, efficient code. – cl_progger Feb 19 '11 at 20:06
  • 2
    @cl_progger: if you want small, efficient, readable C code then I think the best thing to do is to write it in C. OK, so CUDA would permit you to use C++ for what you want, but if OpenCL doesn't and the same configuration code needs to work on both... Not everything in the world needs to be a class, does it? ;-) – Steve Jessop Feb 21 '11 at 01:35
  • That's true. Unfortunately the program for CUDA exists and there are classes for that program... Perhaps converting C to C++ is easier? – cl_progger Feb 21 '11 at 14:26
  • 6
    Just for note. `llc -c` option seems to be deprecated. [The manual](http://llvm.org/docs/CommandGuide/llc.html) doesn't mention about it anymore. – eonil Sep 04 '13 at 07:13
  • 3
    It's considered buggy and no one wants to maintain it (at least that's the reason for its deprecation) – Mikhail Maltsev Oct 09 '17 at 14:54
  • A fork of llvm with the C backend retained is now at https://github.com/JuliaComputing/llvm-cbe – technosaurus Dec 27 '19 at 01:47
18

The C++ FAQ has a list of possibilities: Is it possible to convert C++ to C?.

In short, it says that you can't expect this to give you particularly readable code. Think of the complexities involved; multiple inheritance, virtual-function resolution, templates, operator overloading, etc., etc. There's no clean succinct way of expressing these concepts in pure C. If all you're after is compilable C, though, then this is probably the way to go.

0xC0000022L
  • 18,189
  • 7
  • 69
  • 131
Oliver Charlesworth
  • 252,669
  • 29
  • 530
  • 650
  • Actually, nothing you list is terribly difficult to implement in portable, pure C – though it can be verbose. When you have MI, however, pointers to member functions and pointers to data members are harder (in portable, pure C). – Fred Nurk Feb 19 '11 at 11:23
  • @Fred: I don't claim that these are *difficult* to implement, but they are extremely *tedious* to implement! But yes, you're right; the main obstacle is verbosity. – Oliver Charlesworth Feb 19 '11 at 11:25
  • For example, struct A : B, C {}; becomes struct A { struct B __base_subobject_1; struct C __base_subobject_2; };. Virtual function resolution can happen through a vtable, which is just an array of function pointers (most people are familiar with this). Templates could work by instantiating them exactly as C++ requires, using names like \_\_vector\_\_int for vector. Operator overloading can simply be a named function: __SomeType_add for a + b; since you resolve the overload in C++, you know exactly what the C calls. – Fred Nurk Feb 19 '11 at 11:26
  • 1
    Ah, I must have misread it as "complexities... There's no clean way of expressing these concepts in pure C." There are clean ways for those listed! – Fred Nurk Feb 19 '11 at 11:27
  • @Fred: I've slightly modified the wording in my answer! – Oliver Charlesworth Feb 19 '11 at 11:33
10

The Comeau compiler seems to be able to do that. From Wikipedia "Rather than produce an executable directly, Comeau C/C++ outputs C code and requires a separate C compiler in order to produce the final program."

I have never tried it, though.

René Nyffenegger
  • 35,550
  • 26
  • 140
  • 232
  • Comeau works as described. It tailors the C output for the specific backend compiler with knowledge of how each backend compiler optimizes code. – Thomas Edleson Feb 19 '11 at 11:14
2
  1. Comeau Computing offers a compiler based on Edison Design Group's front end that outputs C code.
  2. LLVM is a downloadable compiler that emits C code. See also here and here. Here is an example of C++ to C conversion via LLVM.
  3. Cfront, the original implementation of C++, done by Bjarne Stroustrup and others at AT&T, generates C code. However it has two problems: it's been difficult to obtain a license since the mid 90s when it started going through a maze of ownership changes, and development ceased at that same time and so it doesn't get bug fixes and doesn't support any of the newer language features (e.g., exceptions, namespaces, RTTI, member templates).
  4. Contrary to popular myth, as of this writing there is no version of g++ that translates C++ to C. Such a thing seems to be doable, but I am not aware that anyone has actually done it (yet).

http://www.cs.technion.ac.il/users/yechiel/c++-faq/convert-to-c.html

jcoffland
  • 4,677
  • 35
  • 40
OulinaArt
  • 314
  • 2
  • 11
2
  1. VisualGBD is a Visual Studio extension that allows you to develop in compile for embedded platforms. It's not free but there is a trial. Worth it in my mind if it works for your application.

    https://visualgdb.com

  2. LLVM is a good option.

    http://llvm.org/docs/FAQ.html#translatecxx

    It handles some code, but will fail for more complex implementations as it hasn't been fully updated for some of the modern C++ conventions. So try compiling your code frequently until you get a feel for what's allowed.

    Usage sytax from the command line is as follows for version 9.0.1:

    clang -c CPPtoC.cpp -o CPPtoC.bc -emit-llvm
    clang -march=c CPPtoC.bc -o CPPtoC.c
    

    For older versions (unsure of transition version), use the following syntax:

    llvm-g++ -c CPPtoC.cp -o CPPtoC.bc -emit-llvm
    llc -march=c CPPtoC.bc -o CPPtoC.c
    

    Note that it creates a GNU flavor of C and not true ANSI C. You will want to test that this is useful for you before you invest too heavily in your code. For example, some embedded systems only accept ANSI C.

    Also note that it generates functional but fairly unreadable code. I recommend commenting and maintain your C++ code and not worrying about the final C code.

  3. The Comeau site is dead unfortunately. Coherent is built on comeau and might offer some options. They have prebuilt VMs which have been maintained as recent as 2018.

    https://www.autometer.de/unix4fun/coherent/#inst_coh

  4. CLang is available but has not been updated in a long time

    http://www.softwarepreservation.org/projects/c_plus_plus/cfront/release_3.0.3/source/cfront_3_0_3.tgz

VoteCoffee
  • 3,300
  • 26
  • 31