Jump to content

Linkage (software)

From Wikipedia, the free encyclopedia

In programming languages, particularly the compiled languages like C, C++, and D, linkage describes how names can or can not refer to the same entity throughout the whole program or one single translation unit.

The static keyword is used in C to restrict the visibility of a function or variable to its translation unit. This is also valid in C++. C++98 and C++03 deprecated this usage in favor of anonymous namespaces, but is no longer deprecated in C++11. Also, C++ implicitly treats any const namespace-scope variable as having internal linkage unless it is explicitly declared extern, unlike C.

A name's linkage is related to, but distinct from, its scope. The scope of a name is the part of a translation unit where it is visible. For instance, a name with global scope (which is the same as file-scope in C and the same as the global namespace-scope in C++) is visible in any part of the file. Its scope will end at the end of the translation unit, whether or not that name has been given external or internal linkage.

If the name has external linkage, the entity that name denotes may be referred to from another translation unit using a distinct declaration for that same name, and from other scopes within the same translation unit using distinct declarations. Were the name given internal linkage, such a declaration would denote a distinct entity, although using the same name, but its entity could be referred to by distinct declarations within the same translation unit. A name that has no linkage at all cannot be referred to from declarations in different scopes, not even from within the same translation unit. Examples of such names are parameters of functions and local variables. The details differ between C (where only objects and functions - but not types - have linkage) and C++ and between this simplified overview.

Linkage between languages must be done with some care, as different languages adorn their external symbols differently. A common idiom uses extern "C"]] to link C++ and C code.

C

[edit]

Definition of 'linkage' quoted from ISO/IEC 9899:TC3 (C99 Standard). C uses the term "identifier" where this article uses "name" (the latter of which is what C++ uses to formalize linkage):

An identifier declared in different scopes or in the same scope more than once can be made to refer to the same object or function by a process called linkage.[1]

The following is a common example of linkage:

In demo1.c:

  
// the "extern" qualifier is optional
// by default functions have external linkage
/* extern */ void foo(void);
  
int main(void) {
    foo();
    return 0;  
}

In demo2.c:

  
void foo(void) {
    // actual implementation here...
}

Function foo is declared in two files, with its function body defined in demo2.c. Via linkage, foo called in main() inside demo1.c refers to foo in demo2.c. This is an example of external linkage for a function.

Linking C and C++ code

[edit]

While C and C++ maintain a large degree of source compatibility, the object files their respective compilers produce can have important differences that manifest themselves when intermixing C and C++ code. Notably:

  • C compilers do not name mangle symbols in the way that C++ compilers do.[2]
  • Depending on the compiler and architecture, it also may be the case that calling conventions differ between the two languages.

For these reasons, for C++ code to call a C function foo(), the C++ code must prototype foo() with extern "C". Likewise, for C code to call a C++ function bar(), the C++ code for bar() must be declared with extern "C".

A common practice for header files to maintain both C and C++ compatibility is to make its declaration be extern "C" for the scope of the header:[3]

In foo.h:

// If this is a C++ compiler, use C linkage 
#ifdef __cplusplus
extern "C" {
#endif

// Any symbol declared here gets C linkage
void foo();
int bar(int a, int b);

// If this is a C++ compiler, end C linkage
#ifdef __cplusplus
}
#endif

Differences between C and C++ linkage and calling conventions can also have subtle implications for code that uses function pointers. Some compilers will produce non-working code if a function pointer declared extern "C" points to a C++ function that is not declared extern "C".[4]

For example, the following code:

void qux();
extern "C" void foo(void (*fp)(void));

void bar() {
   foo(qux);
}

Using Sun Microsystems' C++ compiler, this may produce the following warning:

 "test.cpp", line 5: Warning (Anachronism): Formal argument fp of type
 extern "C" void(*)() in call to foo(extern "C" void(*)()) is being passed
 void(*)().

This is because qux() is not declared with C linkage and calling conventions, but is being passed to the C function foo().

C++

[edit]

C++ offers the following forms of linkage:[5][6]

No linkage

[edit]

Names with no linkage are those which may only be reference from the exact scope in which they are declared. For example, local variables, function parameters, and local classes.[6]

Internal linkage

[edit]

Names with internal linkage are those which may be referenced from any scope within the same translation unit. With internal linkage, each translation unit receives its own isolated copy of the symbol. A symbol gets internal linkage if declared static at namespace scope. By default, const, constexpr, and typedef objects also have internal linkage.[6] However, using the inline specifier on an const variable at namespace scope gives it external linkage.[7]

// static symbols receive internal linkage
static int double(int n) {
    return 2 * n;
}

// constexpr implicitly makes it internal linkage
constexpr int MAX_ATTEMPTS = 3;

// inline constexpr makes it external linkage
inline constexpr int MAX_CONNECTIONS = 100;

External linkage

[edit]

Names with external linkage are those which may be referenced from any translation unit across the entire program.[8][9]

// A.cpp
int i = 1; // Actual declaration and definition of i

// B.cpp
extern int i; // Declares the existence of i

// C.cpp
int i = 2; // Error: i is already defined (in A.cpp)
extern int i = 3; // Same error

Module linkage

[edit]

Names with module linkage are those which may be shared across different translation units but only if they belong to the same named module. Such symbols may be accessed by any file part of the module itself, but not from code that imports that module, unless it is explicitly declared export.

Language linkage

[edit]

C linkage is denoted with extern "C", which disables C++ name mangling. It allows C++ programs to link against compiled libraries written purely in C, and allows calling of C++ functions from C. extern "C" code may not expose types or features not present in C (such as classes, templates or exception throwing).

C++ linkage is denoted with extern "C++", and is used to explicitly force C++ linkage conventions. This may be used within extern "C" blocks to force a symbol to have C++ linkage. Additionally, it is used in C++ modules to force something in the module purview to be attached to the global module, allowing symbols with internal linkage from a header to still be attached to the module.

export module wikipedia.examples.mylib;

export extern "C++" {
    // Forces the contents in the header to have global module attachment when exported
    #include <wikipedia/examples/MyLib.hpp>
}

Some compilers may support additional language linkages. For example, GCC supports Java linkage with extern "Java", which is used when referencing Java code compiled by GCJ and used in C++ code to indicate that a symbol that is consumed originates from Java.[10]

For example, from Java:

package org.wikipedia.examples;

public class Foo {
    public int add(int a, int b) {
        return a + b;
    }
}

Then, in C++:

#include <gcj/cni.h>

// Automatically generated header
#include <org/wikipedia/examples/Foo.h>

using org::wikipedia::examples::Foo;

extern "Java" {
    int addThroughJava(int a, int b) {
        Foo* foo = new Foo();
        return foo->add(a, b);
        // Note: foo should not be deleted, as it is a Java-managed garbage collected object
    }
}

D

[edit]

In D, a block of code that is meant to be declared as originating from another language can be marked extern (...):

See also

[edit]

References

[edit]
  1. ^ ISO/IEC 9899. Official C99 documents, including technical corrigenda and a rationale. As of 2007 the latest version of the standard is "ISO/IEC 9899:TC3" (PDF). (3.61 MiB)
  2. ^ "IBM Knowledge Center". ibm.com.
  3. ^ "IBM Knowledge Center". ibm.com.
  4. ^ "Oracle Documentation". Docs.sun.com. Archived from the original on 3 April 2009. Retrieved 18 August 2013.
  5. ^ cppreference.com. "Storage class specifiers". cppreference.com. cppreference.com. Retrieved 18 May 2026.
  6. ^ a b c Microsoft Learn. "Translation units and linkage". learn.microsoft.com. Microsoft Learn. Retrieved 28 January 2025.
  7. ^ cppreference.com. "inline specifier". cppreference.com. cppreference.com. Retrieved 18 May 2026.
  8. ^ IBM (8 April 2025). "External linkage". ibm.com. IBM.
  9. ^ Microsoft Learn (3 December 2021). "extern (C++)". learn.microsoft.com. Microsoft Learn.
  10. ^ GNU Project. "7.7 C++-Specific Variable, Function, and Type Attributes". gcc.gnu.org. GNU Project. Retrieved 19 May 2026.
  11. ^ D Language Foundation (18 May 2026). "Interfacing to C". dlang.org. D Language Foundation.
  12. ^ D Language Foundation (18 May 2026). "Interfacing to C++". dlang.org. D Language Foundation.
  13. ^ D Language Foundation (18 May 2026). "Interfacing to Objective-C". dlang.org. D Language Foundation.