Як викликати функції С із ескізу Ардуїно?


10

Мені хотілося б знати, чи є спосіб викликати функції, що містяться у файлах C, за допомогою ескізу Arduino?

Мій файл C оголошує та визначає функцію. Щоб зберегти введення брудного визначення функції в мій ескіз Ардуїно, я хотів би викликати функцію прямо з ескізу.

Чи є стандартний спосіб зробити це за допомогою Arduino та C? Ось ескіз:

#include "crc16.h";

void setup(){

}

void loop(){

  CalculateCRC16("<09M", 4);

}

і це оброблений файл C:

#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;
}

Чи є причина, чому ваш файл повинен використовувати C замість C ++?
Пітер Блумфілд

Власне, так. Коли я намагаюся скомпілювати файл за допомогою C ++, виникають помилки, але це не вільно в C. Помилка викликана рядками: const void *c_ptrі const uint8_t *c = c_ptr;. У повідомленні про помилку згадується недійсна конверсія між типами.
ім’я користувача

4
Чи можете ви опублікувати 2 файли коду (або спрощену їх мінімальну версію), які видають помилку, і скопіювати та вставити повідомлення про помилку повністю?
drodri

Повідомлення про помилки не такі гарні: 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

Відповіді:


10

Ви можете викреслити "C" #include, як описано нижче:

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

void setup(){
}

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

І файл crc16.h може бути (деякі незначні виправлення, #pragma один раз, акторський склад):

#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;
}

Дякую, зараз він працює чудово. Чи можете ви поясніть, будь ласка, необхідність прагми?
ім’я користувача

1
Звичайно, це хороша практика, хоча вона не потрібна у вашому прикладі. Це дозволяє уникнути того, що один і той самий файл заголовка два рази включається до компіляційного файла. Уявіть, що a.cpp -> (bh і ch) і bh-> ch це буде дублювати вміст ch під час компіляції a.cpp. #Pragma одного разу уникає цього. Для цього також розповсюджені директиви щодо захисту #ifndef _MY_FILE_H_INCLUDED #define _MY_FILE_H_INCLUDED. Однак зауважте, що, як вказує Пітер Р. Блумфілд, може бути краще помістити реалізацію CalculateCRC16 у файл cpp і залишити лише декларацію у файлі заголовка.
drodri

Гаразд, я бачу, що це стає проблемою, коли код стає все складнішим. Дякую за пораду.
ім'я користувача

4

Вашу функцію CRC можна легко перетворити на C ++, щоб вона могла перейти у файл * .cpp. Все, що вам потрібно зробити, - це використовувати явний формат під час ініціалізації cвказівника. Ось "правильний" C ++ спосіб це зробити:

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

Однак старий акторський склад також може працювати:

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

Проблема полягає в тому, що C може бути трохи більш дозволеним щодо того, щоб ви могли неявно перетворювати покажчики між типами. Щоб зробити це в C ++, вам потрібно чітко сказати компілятору, що перетворення є навмисним.


1

Так, просто скопіюйте рядок декларації у свій ескіз:

extern "C" {
    void myfunction(int arg);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.