This proposal defines the concrete technical mechanisms for C++
interoperability. It specifies the precise syntax and semantics for importing
C++ APIs. This includes the import Cpp library "..." and implicitly importing
C++ built-in entities, and the establishment of the Cpp package as the
dedicated namespace for all imported entities.
While Carbon has a stated goal of seamless C++ interoperability, and a high-level direction has been agreed upon, there is currently no concrete, specified mechanism for developers to actually import and use C++ APIs. This proposal aims to address that by defining the specific syntax and semantics for C++ interoperability.
One of Carbon's primary goals is to be a successor language. This strategy is entirely dependent on seamless, bidirectional interoperability with C++ to enable large-scale adoption and migration for existing C++ codebases.
This proposal provides the necessary details on how C++ APIs should be imported.
We propose to formalize the following specific design elements for C++ interoperability:
The Cpp Package: All imported C++ entities, whether from built-ins or
library headers (see below), will be nested within a dedicated Cpp
package. This prevents name collisions with Carbon code and makes the
language boundary explicit.
fn UseCppTypes() {
// Access C++ types and functions by way of the Cpp package
var circle: Cpp.Circle = Cpp.GenerateCircle();
Cpp.PrintCircle(circle);
}
Importing C++ Header-Defined APIs: To import C++ APIs from a specific
library header file (for example, <vector> or "my_library.h"), Carbon
code will use the import Cpp library "..." directive.
import Cpp library "<vector>";
import Cpp library "circle.h";
Importing C++ Built-in Entities: To access fundamental C++ types (such
as int, bool, etc.), no explicit importing is needed and writing
Cpp.int and Cpp.bool would just work.
Cpp package and namespace mappingAll C++ declarations will be imported into the Cpp package. C++ namespaces
will be mapped to nested packages within Cpp. For example, a C++ function
std::string::find would be accessible in Carbon as Cpp.std.string.find. The
C++ global namespace will be mapped to the Cpp package itself. So a function
MyGlobalFunction in the C++ global namespace will be Cpp.MyGlobalFunction in
Carbon.
import Cpp library directiveThe import Cpp library "..." directive will instruct the Carbon compiler to
parse the specified C++ header file. The compiler will use the standard C++
include paths to locate the header. Additional paths can be provided through
compiler flags.
The Carbon compiler will leverage a C++ front-end, like Clang, to parse the headers. This ensures a high degree of compatibility with existing C++ code. Only the declarations from the header will be imported, not the definitions (unless they are inline).
A set of fundamental C++ types will be available within the Cpp package
without any explicit import directive. Mapping examples:
| C++ Type | Carbon Type |
|---|---|
int |
Cpp.int |
unsigned int |
Cpp.unsigned_int |
double |
Cpp.double |
float |
Cpp.float |
bool |
Cpp.bool |
char |
Cpp.char |
This automatic availability of built-in types is designed to make basic interoperability tasks as smooth as possible.
import Cpp library "..." directives
make all dependencies on C++ headers.Cpp package is a critical design
element. It provides a clean, unambiguous namespace for all imported C++
code.int) require some import Cpp directive like
import Cpp;.
Cpp is a special package, it should be
implicitly imported, similar to Carbon's prelude.