简体   繁体   English

如何将arduino库与标准C代码一起使用

[英]How do I use arduino libraries with standard C code

I am using Eclipse kepler for AVR development. 我正在使用Eclipse kepler进行AVR开发。 The code that I have is C (Open Source), and I've gotten it adjusted so it runs perfectly. 我拥有的代码是C(开源),我已经调整它以便它完美运行。 My target is an ATmega2560, in the form of an arduino mega2560. 我的目标是ATmega2560,采用arduino mega2560的形式。 Using the arduino board is strictly for hardware convenience; 使用arduino板严格用于硬件方便; we are developing the hardware to be a custom board with most of the core arduino mega2560 components. 我们正在开发硬件作为定制板,其中包含大多数核心arduino mega2560组件。

I need to use several libraries with this project that are only available as arduino libraries, namely libraries for an e-paper screen (from seeedstudio) and Nordic's BLE nRF8001. 我需要在这个项目中使用几个库,它们只能用作arduino库,即电子纸屏幕库(来自seeedstudio)和Nordic的BLE nRF8001。

If I create a new arduino project using the plugin in eclipse, I can build and run the tests for the arduino libraries perfectly. 如果我在eclipse中使用插件创建一个新的arduino项目,我可以完美地构建和运行arduino库的测试。

When I try to merge the 2 code bases together, I can't seem to call the functions in the added arduino libraries - if I call them the compiler throws a linking error. 当我尝试将两个代码库合并在一起时,我似乎无法调用添加的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

As a test, I'm just trying to call a basic "write to display" call in eInk.cpp from main.c: 作为测试,我只是尝试从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

}

Is a static library built from the arduino cores the way to go here? 是一个从arduino核心构建的静态库的方式吗? I've tried it (though it seems most of the procedures are outdated) and the libraries do not want to link/be called. 我已经尝试过了(虽然看起来大部分程序已经过时)并且库不想链接/被调用。

What is the correct procedure for including C++/Arduino calls in my C code? 在我的C代码中包含C ++ / Arduino调用的正确步骤是什么? I've tried using extern "C" {function()}; 我尝试过使用extern“C”{function()}; in my .cpp files and .h files but to no use. 在我的.cpp文件和.h文件中,但没有用。

Thank you for any help or pointers to where I can figure it out for myself. 感谢您提供任何帮助或指示我可以自己解决的问题。

You can try to compile your C code as C++ by simply renaming the files to *.CPP, but chances are that you have to modify your code to make it compile as C++ code. 您可以尝试通过简单地将文件重命名为* .CPP来将C代码编译为C ++,但是您可能需要修改代码以使其编译为C ++代码。 There are things that are allowed for C, but not for C++ (like calling functions that are not declared). 有些东西是C允许的,但不适用于C ++(比如调用未声明的函数)。

The other solution is to wirte wrappers around the C++ functions that you want to use from C. You have to consider two limitations of C against C++: 另一个解决方案是围绕要在C中使用的C ++函数包装。您必须考虑C对C ++的两个限制:

  1. C is not object oriented C不是面向对象的
  2. C does not support overloading of functions C不支持函数重载

This example for Serial.print() shows how you can handle this with a wrapper: Serial.print()这个示例显示了如何使用包装器处理它:

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

In this example you would write similar functions like SerialPrintFloat() , SerialPrintString() etc. The extern "C" prefix tells the compiler to create the function in a way that makes it callable from C. 在这个例子中,您将编写类似的函数,如SerialPrintFloat()SerialPrintString()SerialPrintString() extern "C"前缀告诉编译器以一种使其可从C调用的方式创建函数。

The error you received above isn't a compiler error, it's a linker error. 您上面收到的错误不是编译器错误,而是链接器错误。 I haven't used Eclipse for Arduino development, I just stick with the Arduino IDE, but the standard Arduino projects expect all of your code to be in a single source file, which it compiles and then links with the Arduino libraries. 我没有使用Eclipse进行Arduino开发,我只是坚持使用Arduino IDE,但是标准的Arduino项目希望你的所有代码都在一个源文件中,它编译然后链接到Arduino库。 Arduino programs don't have a C/UNIX-style "main" function, the standard functions are "setup" and "loop." Arduino程序没有C / UNIX风格的“主”功能,标准功能是“设置”和“循环”。

I recommend going back to one of the Arduino example programs, blink for instance, and watching the console log as Eclipse compiles and links the program. 我建议回到其中一个Arduino示例程序,例如blink,并在Eclipse编译和链接程序时观察控制台日志。 What's happening here is: 这里发生的事情是:

  1. The C/C++ compiler compiles your source code, including setup(), loop(), and any other functions you have created, into an object file. C / C ++编译器将您的源代码(包括setup(),loop()和您创建的任何其他函数)编译到目标文件中。
  2. The Linker links this single object file with the Arduino runtime, and any Arduino libraries you have specified. 链接器将此单个目标文件与Arduino运行时以及您指定的任何Arduino库链接起来。 The output of this is an image of the program, in your example above it's trying to make 'Virgin2ManualArdInsert.elf'. 这个的输出是程序的一个图像,在你上面的例子中它试图制作'Virgin2ManualArdInsert.elf'。
  3. The uploader (probably avrdude) loads this image into your Arduino and resets it. 上传者(可能是avrdude)将此图像加载到您的Arduino中并重置它。
  4. The Arduino comes out of reset and runs your new code. Arduino退出重置并运行新代码。

If your program is reasonably small, say not more than a few hundred lines, just put all the functions in the one source file, then you won't have to learn how to drive the linker. 如果您的程序相当小,比如说不超过几百行,只需将所有函数放在一个源文件中,那么您就不必学习如何驱动链接器。

If you need, for some reason, to have the sources in a separate file (maybe they're shared with another program, or another platform), then you'll have to learn how to get Eclipse to link the object files from your multiple source files. 如果由于某种原因需要将源代码放在一个单独的文件中(可能它们与另一个程序或其他平台共享),那么您将必须学习如何让Eclipse链接来自多个文件的目标文件源文件。 This may just involve adding the sources into your Eclipse project properly, or you may have to write a Makefile or something similar. 这可能只涉及正确地将源添加到Eclipse项目中,或者您可能必须编写Makefile或类似的东西。

As for C vs C++ source code , you can usually drop a C function into a C++ source file and compile it. 对于C vs C ++ 源代码 ,通常可以将C函数放入C ++源文件并进行编译。 There are a few differences, but this way you don't need to worry about "C" linkage or any of that silliness. 有一些差异,但这样你不必担心“C”链接或任何愚蠢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM