Pregunta

El enlazador está informando errores se multiplican definidos para una función en línea.

tengo el siguiente código en un archivo de cabecera:

struct Port_Pin
{
    volatile uint32_t *     port_addr_set_value;    //!< Writing the pin value here sets the pin to high.
    volatile uint32_t *     port_addr_clr_value;    //!< Writing the pin value to this port clears the pin to low.
    volatile uint32_t *     port_addr_read_value;   //!< Address to read pin value.
    volatile uint32_t *     port_addr_enable;       //!< Writing the pin value here enables the pin (for reading or writing).
    volatile uint32_t *     port_addr_disable;      //!< Writing the pin value here disables the pin.
    volatile uint32_t *     port_addr_dir_output;   //!< Writing the pin value here sets the pin as an output.
    volatile uint32_t *     port_addr_dir_input;    //!< Writing the pin value here sets the pin as an input.
    unsigned int            pin_bit_position;       //!< Zero based, where position zero is first bit position.
};

inline void
Write_Port_Pin(const struct Port_Pin *  p_port,
               uint8_t                  bit)
{
    volatile uint32_t * port_addr = 0;
    port_addr = ((bit & 1) == 0) ? p_port->port_addr_clr_value
        : p_port->port_addr_set_value;
    *port_addr = 1 << p_port->pin_bit_position;
    return;
}

I incluye el archivo de encabezado en el archivo de más de una fuente (.c).

Me gustaría tener la función anterior pegada en línea dondequiera que se llama.
¿Existe una técnica para esto sin tener varias definiciones de la función en cada archivo fuente que se incluye? En caso afirmativo, por favor proporcione ejemplo.

necesito la optimización del rendimiento de una plataforma integrada.
¿Son los compiladores o enlazadores suficientemente inteligente como para las funciones en línea cuando se definen en otras unidades de traducción?

Estoy utilizando el compilador verde Hills, 4.2.4 en una plataforma ARM9 integrado. Asumir estándar del lenguaje C pre-2000. Este es el código C no C ++.

¿Fue útil?

Solución

En línea es sólo una sugerencia, no una orden. Sin embargo, en los compiladores generales son lo suficientemente inteligente como para hacer lo correcto (y Green Hills tiene una buena reputación en la medida en que van optimizaciones).

Hacer la función de 'static inline', lo que evitará que el compilador de hacer el símbolo exportable. Eso debería arreglar sus múltiples errores de enlace definición ... el enlazador se queja de que la misma función se exporta desde varios módulos de fuente.

Otros consejos

Algunas notas importantes:

Parece que no habéis guardado correctamente su cabecera.

#ifndef NAME_H
#define NAME_H
//...contents go here...
#endif // NAME_H

Esto evita múltiples definiciones cuando la cabecera se #included más de una vez.

También parece que usted piensa que puede forzar a un compilador inline su función. Esto no es correcto. Una bandera compilador loco y oscura a un lado, el compilador siempre decidirá si quiere inline su función en el código producido. La palabra clave en línea tiene un significado / propósito diferente de lo que se piensa, ver aquí

No está claro lo que quiere decir por qué "pre-2000 especificación del lenguaje C" -. La última norma se finalizó en 1999. Antes de eso, inline no era una palabra clave en absoluto

El estándar de 1999 dice lo siguiente:

  

Si todas las declaraciones ámbito de archivo   para una función en una unidad de traducción   incluir la función inline   especificador sin extern, entonces la   definición en la que la unidad de traducción es   un definición en línea . una línea   definición no proporciona una   definición externa para la función,   y no prohíbe una externa   definición en otra traducción   unidad. Una definición en línea proporciona una   alternativa a una definición externa,   el que un traductor puede utilizar para   implementar cualquier llamada a la función de   la misma unidad de traducción. Es   sin especificar si una llamada al   función utiliza la definición en línea o   la definición externa.

Esto significa que, siempre y cuando usted no tiene una declaración de Write_Port_Pin() con el calificador extern, el compilador no debe generar una definición externa de la función, por lo que no se debe molestar al enlazador. Me presento como un bug a su proveedor compilador si fuera tú.

Si usted tiene definición en línea en .h archivo y lo incluye en muchos archivos .c y intenta compilar una librería usando el compilador armcc. Ahora Si utiliza la opción de compilador --gnu al código de compilación armcc entonces también se vea Definir multiplican error al vincular, porque pone a continuación compilador definición en cada archivo .c y la exporta. Parece al tratar de hacer compatible su código de GCC, obtenemos este inconveniente.

Para evitarlo, puede ser el uso --c99 opción en lugar de --gnu.

y deshacerse de este problema se multiplican definir en los archivos .c debido a las funciones en línea exportar por el compilador.

En C no se puede definir una función con el mismo nombre en varios lugares ya sea en línea o no.

La mejor manera de manejar esto es declarar la función en una cabecera (junto con la definición de la estructura depende, así:

/* port_control.h */

struct Port_Pin              
{              
    volatile uint32_t *     port_addr_set_value;    //!< Writing the pin value here sets the pin to high.              
    volatile uint32_t *     port_addr_clr_value;    //!< Writing the pin value to this port clears the pin to low.              
    volatile uint32_t *     port_addr_read_value;   //!< Address to read pin value.              
    volatile uint32_t *     port_addr_enable;       //!< Writing the pin value here enables the pin (for reading or writing).              
    volatile uint32_t *     port_addr_disable;      //!< Writing the pin value here disables the pin.              
    volatile uint32_t *     port_addr_dir_output;   //!< Writing the pin value here sets the pin as an output.              
    volatile uint32_t *     port_addr_dir_input;    //!< Writing the pin value here sets the pin as an input.              
    unsigned int            pin_bit_position;       //!< Zero based, where position zero is first bit position.              
};              

/* Declare the function here so other modules know about it. */        
inline void              
Write_Port_Pin(const struct Port_Pin *  p_port,              
               uint8_t                  bit);

A continuación, defina la función en un archivo de origen .c en un solo lugar:

/* port_control.c */

#include "port_control.h"

inline void                     
Write_Port_Pin(const struct Port_Pin *  p_port,                     
               uint8_t                  bit)                     
{                     
    volatile uint32_t * port_addr = 0;                     
    port_addr = ((bit & 1) == 0) ? p_port->port_addr_clr_value                     
        : p_port->port_addr_set_value;                     
    *port_addr = 1 << p_port->pin_bit_position;                     
    return;                     
} 

A continuación, # include este archivo de cabecera en todos los archivos .c que llaman a la función.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top