¿Cómo llamar a funciones C desde el boceto de Arduino?


10

Me gustaría saber si hay una manera de llamar a las funciones que están contenidas en los archivos C utilizando un boceto Arduino.

Mi archivo C declara y define una función. Para guardar poner la definición de función desordenada en mi boceto Arduino, me gustaría llamar a la función directamente desde el boceto.

¿Hay una forma estándar de hacer esto usando Arduino y C? Aquí está el boceto:

#include "crc16.h";

void setup(){

}

void loop(){

  CalculateCRC16("<09M", 4);

}

y este es el archivo C recortado:

#include <stdio.h>
#include <stdint.h>

uint16_t crctable[256] =
{
    0x0000, 0x1189,.....



uint16_t // Returns Calculated CRC value
CalculateCRC16( // Call example CalculateCRC16("<09M", 4);
    const void *c_ptr, // Pointer to byte array to perform CRC on
    size_t len)        // Number of bytes to CRC
{

    uint16_t crc = 0xFFFF // Seed for CRC calculation
    const uint8_t *c = c_ptr;

    while (len--)
        crc = (crc << 8) ^ crctable[((crc >> 8) ^ *c++)];

    return crc;
}

¿Hay alguna razón por la cual su archivo tiene que usar C en lugar de C ++?
— Peter Bloomfield

Actualmente, si. Cuando intento compilar el archivo usando C ++, hay errores, pero está libre de errores en C. El error es causado por las líneas: const void *c_ptry const uint8_t *c = c_ptr;. El mensaje de error menciona una conversión no válida entre tipos.
— user_name

44
¿Podría publicar los 2 archivos de código (o una versión mínima simplificada de ellos) que producen el error, y copiar y pegar el mensaje de error completo?
— drodri

Los mensajes de error no son tan bonitos: In function uint16_t CalculateCRC16(uint16_t, const void*, size_t)': 46 invalid conversion from const void * 'toconst uint8_t*' In function int main()': 57 system' undeclared (first use this function) (Each undeclared identifier is reported only once for each function it appears in.)
— user_name el

Respuestas:


10

Puede externar "C" #incluir de la siguiente manera:

extern "C"{
#include "crc16.h"
};

void setup(){
}

void loop(){
  CalculateCRC16("<09M", 4);
}

Y el archivo crc16.h podría ser (algunas correcciones menores, el #pragma una vez, un reparto):

#pragma once

#include <stdio.h>
#include <stdint.h>

uint16_t crctable[2] ={ 0x0000, 0x1189};

uint16_t CalculateCRC16( // Call example CalculateCRC16("<09M", 4);
    const void *c_ptr, // Pointer to byte array to perform CRC on
    size_t len)        // Number of bytes to CRC
{
    uint16_t crc = 0xFFFF; // Seed for CRC calculation
    const uint8_t *c = (const uint8_t *)c_ptr;

    while (len--)
        crc = (crc << 8) ^ crctable[((crc >> 8) ^ *c++)];

    return crc;
}

Gracias, funciona bien ahora. ¿Podría explicar la necesidad de la pragma?
— user_name

1
Claro, es una buena práctica, aunque no es necesaria en su ejemplo. Evita que el mismo archivo de encabezado se incluya dos veces en un archivo de compilación. Imagine a.cpp -> (bh y ch) y bh-> ch Eso duplicará el contenido de ch mientras compila a.cpp. El #pragma una vez evita esto. También las directivas de protección #ifndef _MY_FILE_H_INCLUDED #define _MY_FILE_H_INCLUDED son comunes para esto. Sin embargo, tenga en cuenta que, como señala Peter R. Bloomfield, podría ser mejor poner la implementación de CalculateCRC16 en un archivo cpp y dejar solo la declaración en el archivo de encabezado.
— drodri

Ok, puedo ver que esto se convierte en un problema cuando el código se vuelve cada vez más complicado. Gracias por el consejo.
— user_name

4

Su función CRC se puede convertir fácilmente a C ++ para que pueda ir a un archivo * .cpp. Todo lo que necesita hacer es usar una conversión explícita cuando inicializa su cpuntero. Aquí está la forma 'adecuada' de C ++ para hacerlo:

const uint8_t *c = static_cast<const uint8_t*>(c_ptr);

Sin embargo, un antiguo elenco de estilo C también funcionaría:

const uint8_t *c = (const uint8_t*)c_ptr;

El problema es básicamente que C puede ser un poco más permisivo al permitirle convertir punteros implícitamente entre tipos. Para hacerlo en C ++, debe decirle explícitamente al compilador que la conversión es intencional.


1

Sí, solo copie su línea de declaración en su boceto:

extern "C" {
    void myfunction(int arg);
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.