如何从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 2014年

4
您能否张贴产生错误的2个代码文件(或它们的简化最小版本),然后完整复制并粘贴错误消息?
drodri 2014年

错误消息不是很漂亮: In function uint16_t CalculateCRC16(uint16_t, const void*, size_t)': 46 invalid conversion from const void *'const 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 2014年

Answers:


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

谢谢,现在一切正常。您能解释一下实用的必要吗?
user_name

1
当然,这是个好习惯,尽管您的示例中并不需要。这样可以避免将同一头文件两次包含在编译文件中。想象一下a.cpp->(bh和ch)和bh-> ch,它将在编译a.cpp时复制ch的内容。#pragma曾经避免这种情况。同样,保护指令#ifndef _MY_FILE_H_INCLUDED #define _MY_FILE_H_INCLUDED也很常见。但是请注意,正如Peter R. Bloomfield指出的那样,将CalculateCRC16的实现放在cpp文件中,而只将声明保留在头文件中,可能会更好。
drodri 2014年

好的,当代码变得越来越复杂时,我可以看到这成为一个问题。感谢您的建议。
user_name 2014年

4

您的CRC函数可以轻松转换为C ++,以便可以将其放入* .cpp文件中。您需要做的就是在初始化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);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.