Arduino 스케치에서 C 함수를 호출하는 방법은 무엇입니까?


10

Arduino 스케치를 사용하여 C 파일에 포함 된 함수를 호출하는 방법이 있는지 알고 싶습니다.

내 C 파일은 함수를 선언하고 정의합니다. 지저분한 함수 정의를 Arduino 스케치에 저장하기 위해 스케치에서 바로 함수를 호출하고 싶습니다.

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_ptrconst uint8_t *c = c_ptr;. 오류 메시지는 유형 간 잘못된 변환을 언급합니다.
user_name

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 할 수 있습니다.

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

void setup(){
}

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

그리고 crc16.h 파일은 다음과 같습니다 (일부 사소한 수정, #pragma once, cast) :

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

고마워, 지금은 잘 작동합니다. pragma의 필요성을 설명해 주시겠습니까?
user_name

1
물론 모범 사례에서는 필요하지 않지만 좋은 방법입니다. 컴파일 파일에 동일한 헤더 파일이 두 번 포함되는 것을 방지합니다. a.cpp를 컴파일하는 동안 ch의 내용을 복제하는 a.cpp-> (bh and ch)와 bh-> ch를 상상해보십시오. #pragma는 이것을 피합니다. 또한 가드 지시문 #ifndef _MY_FILE_H_INCLUDED #define _MY_FILE_H_INCLUDED가 일반적입니다. 그러나 Peter R. Bloomfield가 지적한 것처럼 CalculateCRC16의 구현을 cpp 파일에 넣고 선언 만 헤더 파일에 두는 것이 좋습니다.
drodri

좋아, 코드가 점점 복잡해지면 문제가되는 것을 알 수 있습니다. 충고 감사합니다.
user_name

4

CRC 함수는 * .cpp 파일로 이동할 수 있도록 C ++로 쉽게 변환 할 수 있습니다. c포인터 를 초기화 할 때 명시 적 캐스트를 사용하기 만하면됩니다. 이를 수행하는 '적절한'C ++ 방법은 다음과 같습니다.

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

그러나 오래된 C 스타일 캐스트도 작동합니다.

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

문제는 기본적으로 C가 포인터를 암시 적으로 유형 간 변환하도록 허용하는 데 조금 더 관대하다는 점입니다. C ++에서 수행하려면 변환이 의도적이라는 것을 명시 적으로 컴파일러에 알려야합니다.


1

예, 스케치에 선언 라인을 복사하십시오.

extern "C" {
    void myfunction(int arg);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.