Hacker News new | past | comments | ask | show | jobs | submit login
Cross Language interfaces between C and C++ (2017) (gustedt.wordpress.com)
32 points by signa11 3 days ago | hide | past | favorite | 11 comments





The text in the <includes> has been eaten out by the blog engine it seems. To have bool in C it's <stdbool.h> if anyone wonders.

Also regarding generic constants, C++ allows template variables:

https://en.cppreference.com/w/cpp/language/variable_template


Same for the templates, presumably; `std::atomic` isn’t a type in C++, it’s a template. To be analogous with the C code, this was probably meant to read `std::atomic<unsigned>`.

Also all the C++ template parameters, such as std::complex<float>.

Doesn't this mostly boil down to "C99 and C++ aren't compatible anymore"?

One of the big gotchas of C++ is that lots of people think it's a superset of C, but that's only (mostly) correct for ANSI C (C89).

In my experience not even C99 is completely compatible with C89. One of the initial pain points when clang was young was that GCC used C89 as default, so lots of old stuff didn't build out of the box due to changes to how `inline` behaves or undefined symbols not being allowed anymore.


C99 is not the current C Standard. C11/C17 have more-or-less deprecated the conflicting bit (VLAs) and C++20 adopted some of C's extensions. So, things are better.

In order to compile the ratpak library from Microsoft's calculator using Clang, I ported part of it from C++ to C. It's written in C++17 with some C features that only Visual C++ accepts. Off the top of my head, some of the changes I needed:

* add extern "C" to some of the headers

* include stdbool.h for bool

* include stdint.h for uint64_t et al.

* include stdlib.h and change nullptr to NULL

* change constexpr to enum

* change static_cast to C-style casts

* rewrite a function to take a pointer, rather than a reference

* write a min() function

I probably could have rewritten it as standard C++, but that somehow seemed like a more daunting prospect at the time.


> In C [enumeration constants] are of type int, C++ they are of the enumeration type itself.

> ... C and C++ have different rules for implicit conversion from an to these types, so you better avoid using them [in function parameters]

Correct me if I misunderstood, but don't these differences cancel each other out? For example:

    /* In header file */
    enum Foo { FOO_A, FOO_B };
    void bar(Foo f);
    
    /* In code */
    bar(FOO_A);
In C, FOO_A is an integer, but it's implicitly convertable to Foo so the call to bar is fine. In C++, int cannot implicitly convert to type Foo, but FOO_A is already of type Foo to begin with, so the function call is still fine. (In fact the call to bar() would in a .c or .cpp file so is allowed to be different between the two languages anyway.)

Edit: Another oddity in the article: If you want a function to work with a small number of different types, you would surely use simple function overloading rather than function template specialisation. In general it's a mistake to use function template specialisation, and there's certainly no need to use it here.


I believe:

  enum Foo { FOO_A, FOO_B };
is implicitly convertible to int even in C++.

  enum class Foo { FOO_A, FOO_B };
is not implicitly convertible, but can still be converted using static_cast.

Indeed, but I'm talking about the other way: int -> Foo. The article talked about "different rules for implicit conversion" so I assume they must have been referring to that direction.

This. Only `enum class` gives you a strongly-typed guarantee, `enum` can happily implicitly decay to `int` without any kind of warning. Lots of C libraries use `int` frequently together with enums without any sort of care, and it's too late to change this behaviour without creating an interoperability nightmare. The fact that `int` is not implicitly convertible to an enum type at least still saves you from a death from thousand cuts when a wrong value manages to get into an enum.

The only sane way is to consider `enum` as a deprecated construct in C++ and use it as sparingly as possible, preferably only when interoperability with C makes them unavoidable.


This article is about code that will directly be compiled by both a C and C++ compiler, so indeed `enum class` is not an option here.



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

Search: