Articulo de referencia

Linkage (software)

In programming, 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...

In programming, 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 constnamespace-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

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:

// El calificador "extern" es opcional // Por defecto, las funciones tienen enlace externo /* extern */ void foo ( void ); int main ( void ) { foo (); return 0 ; }

En demo2.c :

void foo ( void ) { // implementación real aquí... }

La función foo()se declara en dos archivos, con su cuerpo definido en demo2.c . Mediante enlace, la llamada en demo1.c hace referencia a la llamada en demo2.c . Este es un ejemplo de enlace externo para una función.foo()main()foo

Vinculación de código C y C++

Si bien C y C++ mantienen un alto grado de compatibilidad de código fuente, los archivos objeto que producen sus respectivos compiladores pueden presentar diferencias importantes que se manifiestan al mezclar código C y C++. En particular:

  • Los compiladores de C no nombran los símbolos mangle de la misma manera que lo hacen los compiladores de C++. [ 2 ]
  • Dependiendo del compilador y la arquitectura, también puede darse el caso de que las convenciones de llamada difieran entre los dos lenguajes.

Por estas razones, para que el código C++ llame a una función C foo(), el código C++ debe prototiparfoo() con . Del mismo modo, para que el código C llame a una función C++ , el código C++ para debe declararse con .extern"C"bar()bar()extern"C"

Una práctica común para los archivos de cabecera para mantener la compatibilidad con C y C++ es hacer que su declaración sea para el ámbito de la cabecera: [ 3 ]extern"C"

En foo.h :

// Si se trata de un compilador de C++, utilice el enlace de C #ifdef __cplusplus extern "C" { #endif// Cualquier símbolo declarado aquí obtiene enlace C void foo (); int bar ( int a , int b );// Si se trata de un compilador de C++, finaliza el enlace con C #ifdef __cplusplus } #endif

Las diferencias entre las convenciones de enlace y llamada de C y C++ también pueden tener implicaciones sutiles para el código que utiliza punteros a funciones . Algunos compiladores producirán código que no funciona si un puntero a función declarado apunta a una función de C++ que no está declarada . [ 4 ]extern"C"extern"C"

Por ejemplo, el siguiente código:

void qux ();extern"C"voidfoo(void(*fp)(void));voidbar(){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++

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

No linkage

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

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 linkagestaticintdouble(intn){return2*n;}// constexpr implicitly grants internal linkageconstexprsize_tMAX_ATTEMPTS=3;// inline constexpr grants external linkageinlineconstexprsize_tMAX_CONNECTIONS=100;

External linkage

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

// A.cppinti=1;// Actual declaration and definition of i// B.cppexterninti;// Declares the existence of i// C.cpp int i = 2 ; // Error: i ya está definido (en A.cpp) extern int i = 3 ; // Mismo error

Enlace de módulos

Los nombres con enlace de módulo son aquellos que pueden compartirse entre diferentes unidades de traducción, pero solo si pertenecen al mismo módulo . Se puede acceder a dichos símbolos desde cualquier archivo que forme parte del módulo, pero no desde el código que importa ese módulo, a menos que se declare explícitamente export.

Enlace lingüístico

El enlace C se denota con , que desactiva la modificación de nombres de C++ . Permite que los programas C++ se enlacen con bibliotecas compiladas escritas puramente en C, y permite llamar a funciones C++ desde C. El código puede no exponer tipos o características que no estén presentes en C (como clases , plantillas o lanzamiento de excepciones ).extern"C"extern"C"

El enlace de C++ se denota con `<link>` y se utiliza para forzar explícitamente las convenciones de enlace de C++. Esto puede usarse dentro de bloques para forzar que un símbolo tenga enlace de C++. Además, se usa en módulos de C++ para forzar que algo dentro del ámbito del módulo se adjunte al módulo global, permitiendo que los símbolos con enlace interno de un archivo de cabecera sigan adjuntos al módulo.extern"C++"extern"C"

exportar módulo wikipedia.ejemplos.mylib ;export extern "C++" { // Fuerza que el contenido del encabezado tenga una conexión de módulo global cuando se exporta #include <wikipedia/examples/MyLib.hpp> }

Algunos compiladores pueden admitir enlaces de lenguaje adicionales. Por ejemplo, GCC admite el enlace de Java con , que se utiliza al hacer referencia a código Java compilado por GCJ y se utiliza en código C++ para indicar que un símbolo que se consume proviene de Java. [ 10 ]extern"Java"

Por ejemplo, desde Java:

paquete org.wikipedia.examples ;clase pública Foo { int público agregar ( int a , int b ) { return a + b ; } }

Luego, en C++:

#incluir <gcj/cni.h>// Encabezado generado automáticamente #include <org/wikipedia/examples/Foo.h>usando org :: wikipedia :: ejemplos :: Foo ;extern "Java" { int addThroughJava ( int a , int b ) { Foo * foo = new Foo (); return foo -> add ( a , b ); // Nota: foo no debe eliminarse, ya que es un objeto gestionado por el recolector de basura de Java } }

D

En D , un bloque de código que se pretende declarar como proveniente de otro lenguaje puede marcarse :extern(...)

Óxido

En Rust , se utiliza para marcar el enlace C, y siempre es , ya que Rust no puede garantizar la seguridad de las funciones externas. [ 15 ]extern"C"unsafe

use std :: ffi ::{ CString , c_char };unsafe extern "C" { fn puts ( s : * const c_char ) -> i32 ; }fn main () { let s = CString :: new ( "Hello from Rust!" ). unwrap ();inseguro { puts ( s . as_ptr ()); } }

Mientras tanto, para exponer las funciones de Rust a C:

#[unsafe(no_mangle)] pub extern "C" fn add ( a : i32 , b : i32 ) -> i32 { a + b }

Rust ofrece los siguientes bloques externos: [ 16 ]

  • unsafeextern"Rust"(Convención de llamada predeterminada en Rust)
  • unsafeextern"C"(la ABI de C predeterminada)

Existen otros bloques específicos del sistema, muchos de los cuales corresponden a atributos del compilador C/C++, por ejemplo, correspondientes a .unsafeextern"stdcall"[[gnu::stdcall]]

Véase también

Referencias

  1. ISO/IEC 9899. Documentos oficiales C99, incluyendo correcciones técnicas y una justificación. A partir de 2007, la última versión de la norma es "ISO/IEC 9899:TC3" (PDF) . (3,61 MiB ) 
  2. "Centro de conocimiento de IBM" . ibm.com .
  3. "Centro de conocimiento de IBM" . ibm.com .
  4. "Documentación de Oracle" . Docs.sun.com. Archivado del original el 3 de abril de 2009. Consultado el 18 de agosto de 2013 .
  5. cppreference.com. "Especificadores de clase de almacenamiento" . cppreference.com . cppreference.com . Consultado el 18 de mayo de 2026 .
  6. 1 2 3 Microsoft Learn. "Unidades de traducción y vinculación" . learn.microsoft.com . Microsoft Learn . Consultado el 28 de enero de 2025 .
  7. cppreference.com. "especificador en línea" . cppreference.com . cppreference.com . Consultado el 18 de mayo de 2026 .
  8. IBM (8 de abril de 2025). "Enlace externo" . ibm.com . IBM.
  9. Microsoft Learn (3 de diciembre de 2021). "extern (C++)" . learn.microsoft.com . Microsoft Learn.
  10. Proyecto GNU. "7.7 Atributos de variables, funciones y tipos específicos de C++" . gcc.gnu.org . Proyecto GNU . Consultado el 19 de mayo de 2026 .
  11. Fundación del Lenguaje D (18 de mayo de 2026). "Interfaz con C" . dlang.org . Fundación del Lenguaje D.
  12. Fundación del Lenguaje D (18 de mayo de 2026). "Interfaz con C++" . dlang.org . Fundación del Lenguaje D.
  13. Fundación del Lenguaje D (18 de mayo de 2026). "Interfaz con Objective-C" . dlang.org . Fundación del Lenguaje D.
  14. Fundación del Lenguaje D (10 de octubre de 2025). "dmd.mangle - Lenguaje de programación D" . dlang.org . Fundación del Lenguaje D.
  15. Los desarrolladores de Rust (26 de junio de 2026). "Palabra clave extern" . docs.rust-lang.org . Los desarrolladores de Rust.
  16. Los desarrolladores de Rust (25 de junio de 2026). "Bloques externos" . docs.rust-lang.org . Los desarrolladores de Rust.