【问题标题】:How do I use arduino libraries with standard C code如何使用带有标准 C 代码的 arduino 库
【发布时间】:2014-08-30 16:12:34
【问题描述】:

我正在使用 Eclipse 开普勒进行 AVR 开发。 我拥有的代码是 C(开源),我已经对其进行了调整,因此它可以完美运行。我的目标是 arduino mega2560 形式的 ATmega2560。 使用arduino板严格是为了硬件方便;我们正在将硬件开发为具有大多数核心 arduino mega2560 组件的定制板。

我需要在这个项目中使用几个库,这些库只能作为 arduino 库使用,即用于电子纸屏幕的库(来自 seeedstudio)和 Nordic 的 BLE nRF8001。

如果我在 eclipse 中使用插件创建一个新的 arduino 项目,我可以完美地为 arduino 库构建和运行测试。

当我尝试将 2 个代码库合并在一起时,我似乎无法调用添加的 arduino 库中的函数 - 如果我调用它们,编译器会引发链接错误。

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

作为测试,我只是想从 main.c 调用 eInk.cpp 中的基本“写入显示”调用:

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

}

从 arduino 内核构建的静态库是否可以实现?我已经尝试过了(尽管似乎大多数程序都已过时)并且库不想链接/被调用。

在我的 C 代码中包含 C++/Arduino 调用的正确程序是什么? 我试过使用 extern "C" {function()};在我的 .cpp 文件和 .h 文件中,但没有用。

感谢您提供任何帮助或指示我可以自己解决的问题。

【问题讨论】:

  • “编译器抛出链接错误” - 那会是什么错误?
  • 您可以使用 gcc 选项 -Wl,--verbose 查看有关链接错误的详细信息
  • 为清楚起见添加了代码 sn-ps。
  • 您是否尝试过使用 C++ 编译器进行编译?它仍应编译您的代码,并且本机支持 C++。

标签: c++ c eclipse arduino avr


【解决方案1】:

您可以尝试将您的 C 代码编译为 C++,只需将文件重命名为 *.CPP,但您可能必须修改您的代码以使其编译为 C++ 代码。有些东西是 C 允许的,但 C++ 是不允许的(比如调用未声明的函数)。

另一种解决方案是围绕要从 C 中使用的 C++ 函数编写包装器。 您必须考虑 C 对 C++ 的两个限制:

  1. C 不是面向对象的
  2. C 不支持函数重载

Serial.print() 的这个示例展示了如何使用包装器处理此问题:

extern "C" void SerialPrintInteger( int value )
{
    Serial.print( value );
}

在此示例中,您将编写类似的函数,例如 SerialPrintFloat()、SerialPrintString() 等。 extern "C" 前缀告诉编译器以一种可以从 C 调用的方式创建函数。

【讨论】:

    【解决方案2】:

    您在上面收到的错误不是编译器错误,而是链接器错误。我没有使用 Eclipse 进行 Arduino 开发,我只是坚持使用 Arduino IDE,但标准的 Arduino 项目希望您的所有代码都在一个源文件中,它会编译然后与 Arduino 库链接。 Arduino 程序没有 C/UNIX 风格的“main”函数,标准函数是“setup”和“loop”。

    我建议回到 Arduino 示例程序之一,例如闪烁,并在 Eclipse 编译和链接程序时查看控制台日志。这里发生的事情是:

    1. C/C++ 编译器将您的源代码(包括 setup()、loop() 和您创建的任何其他函数)编译到目标文件中。
    2. 链接器将此单个目标文件与 Arduino 运行时以及您指定的任何 Arduino 库链接起来。它的输出是程序的图像,在上面的示例中,它试图制作“Virgin2ManualArdInsert.elf”。
    3. 上传者(可能是 avrdude)将此图像加载到您的 Arduino 中并重置它。
    4. Arduino 退出重置并运行您的新代码。

    如果您的程序相当小,比如不超过几百行,只需将所有函数放在一个源文件中,那么您就不必学习如何驱动链接器。

    如果您出于某种原因需要将源文件保存在单独的文件中(也许它们与另一个程序或另一个平台共享),那么您必须学习如何让 Eclipse 链接目标文件从您的多个源文件。这可能只涉及将源代码正确地添加到您的 Eclipse 项目中,或者您可能必须编写一个 Makefile 或类似的东西。

    至于 C 与 C++源代码,您通常可以将 C 函数放入 C++ 源文件并进行编译。有一些区别,但这样您就不必担心“C”链接或任何愚蠢的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-12
      • 1970-01-01
      • 1970-01-01
      • 2016-10-01
      • 2011-05-11
      • 2017-10-03
      相关资源
      最近更新 更多