c++ - utiles - ¿Cómo utilizo las librerías Arduino con el código C estándar?
librerias utiles para arduino (2)
Puede tratar de compilar su código C como C ++ simplemente cambiando el nombre de los archivos a * .CPP, pero es probable que tenga que modificar su código para hacerlo compilar como código C ++. Hay cosas que están permitidas para C, pero no para C ++ (como funciones de llamada que no están declaradas).
La otra solución es wirte envoltorios alrededor de las funciones de C ++ que desea utilizar de C. Debe tener en cuenta dos limitaciones de C frente a C ++:
- C no está orientado a objetos
- C no admite la sobrecarga de funciones
Este ejemplo para Serial.print()
muestra cómo puede manejar esto con un contenedor:
extern "C" void SerialPrintInteger( int value )
{
Serial.print( value );
}
En este ejemplo, escribiría funciones similares como SerialPrintFloat()
, SerialPrintString()
etc. El prefijo extern "C"
le dice al compilador que cree la función de forma tal que sea invocable desde C.
Estoy usando Eclipse Kepler para el desarrollo de AVR. El código que tengo es C (Código Abierto), y lo he ajustado para que funcione perfectamente. Mi objetivo es un ATmega2560, en la forma de un arduino mega2560. El uso de la placa Arduino es estrictamente para la comodidad del hardware; estamos desarrollando el hardware para que sea una placa personalizada con la mayoría de los componentes core arduino mega2560.
Necesito usar varias bibliotecas con este proyecto que solo están disponibles como bibliotecas arduino, a saber, bibliotecas para una pantalla de papel electrónico (de seeedstudio) y BLE nRF8001 de Nordic.
Si creo un nuevo proyecto arduino usando el complemento en eclipse, puedo construir y ejecutar las pruebas para las bibliotecas Arduino perfectamente.
Cuando trato de fusionar las 2 bases de código juntas, parece que no puedo invocar las funciones en las bibliotecas de Arduino añadidas; si las llamo, el compilador arroja un error de enlace.
Building target: Virgin2ManualArdInsert.elf
Invoking: AVR C Linker
avr-gcc -Wl,-Map,Virgin2ManualArdInsert.map -mmcu=atmega2560 -o "Virgin2ManualArdInsert.elf" ./avr/adc.o ./avr/eeprom.o ./avr/lcd_and_input.o ./avr/main.o ./avr/strings.o ./avr/unimplemented.o ./avr/usart.o ./aes.o ./baseconv.o ./bignum256.o ./ecdsa.o ./endian.o ./fft.o ./fix16.o ./hash.o ./hmac_sha512.o ./messages.pb.o ./p2sh_addr_gen.o ./pb_decode.o ./pb_encode.o ./pbkdf2.o ./prandom.o ./ripemd160.o ./sha256.o ./statistics.o ./stream_comm.o ./test_helpers.o ./transaction.o ./wallet.o ./xex.o
./avr/main.o: In function `main'':
main.c:(.text.startup.main+0xc): undefined reference to `writeEink''
collect2: error: ld returned 1 exit status
makefile:53: recipe for target ''Virgin2ManualArdInsert.elf'' failed
make: *** [Virgin2ManualArdInsert.elf] Error 1
Como prueba, intento llamar a una llamada básica de "escritura para mostrar" en eInk.cpp desde main.c:
extern "C"{
void writeEink()
{
EPAPER.begin(EPD_SIZE); // setup epaper, size
EPAPER.setDirection(DIRNORMAL); // set display direction
eSD.begin(EPD_SIZE);
GT20L16.begin();
// int timer1 = millis();
EPAPER.drawString("testing", 10, 10);
EPAPER.drawNumber(12345, 60, 40);
EPAPER.drawFloat(-1.25, 2, 80, 65);
EPAPER.display(); // use only once
}
¿Es una biblioteca estática construida a partir de los núcleos arduino el camino a seguir aquí? Lo probé (aunque parece que la mayoría de los procedimientos están desactualizados) y las bibliotecas no quieren vincular / llamar.
¿Cuál es el procedimiento correcto para incluir llamadas C ++ / Arduino en mi código C? He intentado usar extern "C" {function ()}; en mis archivos .cpp y .h pero sin uso.
Gracias por cualquier ayuda o consejos sobre dónde puedo resolverlo por mí mismo.
El error que recibió arriba no es un error del compilador, es un error del enlazador. No he usado Eclipse para el desarrollo de Arduino, simplemente me quedo con el IDE de Arduino, pero los proyectos estándar de Arduino esperan que todo tu código esté en un único archivo fuente, que compila y luego se vincula con las bibliotecas de Arduino. Los programas Arduino no tienen una función "principal" al estilo C / UNIX, las funciones estándar son "configuración" y "bucle".
Recomiendo volver a uno de los programas de ejemplo de Arduino, pestañear, por ejemplo, y ver el registro de la consola cuando Eclipse compila y vincula el programa. Lo que está sucediendo aquí es:
- El compilador C / C ++ compila su código fuente, incluyendo setup (), loop () y cualquier otra función que haya creado, en un archivo de objeto.
- El Enlazador vincula este único archivo objeto con el tiempo de ejecución Arduino y cualquier biblioteca Arduino que haya especificado. El resultado de esto es una imagen del programa, en su ejemplo anterior está tratando de hacer ''Virgin2ManualArdInsert.elf''.
- El cargador (probablemente avrdude) carga esta imagen en su Arduino y la reinicia.
- El Arduino sale de reinicio y ejecuta su nuevo código.
Si su programa es razonablemente pequeño, por ejemplo, no más de unos pocos cientos de líneas, simplemente coloque todas las funciones en el archivo fuente, entonces no tendrá que aprender a manejar el enlazador.
Si necesita, por algún motivo, tener las fuentes en un archivo separado (tal vez se las comparta con otro programa u otra plataforma), entonces tendrá que aprender cómo hacer que Eclipse vincule los archivos objeto de su múltiple archivos fuente. Esto puede implicar agregar las fuentes en su proyecto de Eclipse correctamente, o puede que tenga que escribir un archivo Makefile o algo similar.
En cuanto al código fuente C contra C ++, generalmente puede colocar una función C en un archivo fuente C ++ y compilarlo. Hay algunas diferencias, pero de esta manera no tiene que preocuparse por el enlace "C" o cualquiera de esas tonterías.