Super169 发表于 2014-4-13 14:30:55

寫庫時如把程式分拆開, 如何 include 進來?

寫了一個簡單 OLED 12864 的庫, 本想分享出來.
一直使用 Sublime Text 2 開發, 在最後測試時, 考慮到用家可能是用 arduino 的 IDE, 所以嘗試在 arduino IDE 上再測試一次.
結果很奇怪的, 分拆出來的部份, 都出了 " multiple definition" 的錯誤.

我再三檢查了, 絕不可能有重複的, 甚至嘗試加入一些檢測 (#ifdef _xxx_ 再 #define _xxx_ 之類, 避免同一段程式 compile 再次 compile),
結果也是一樣.

但同樣的程式, 在 Sublime Text 2 之下, 是完全沒有問題, 可以正常 compile 並 upload 到 arduino 板上執行的.

以下是之前測試時的片段 (只少了 testMsg 一部份), 同一個程式在不同 Arduino 板 (Nano 及 UNO) 及 不同顯示晶片 (SSD1306 及 SH1106) 中執行也是沒有問題的.
但在不同的 IDE 下出現了不同的結果.
http://v.youku.com/v_show/id_XNjk2NzA0MjI4.html


現在有點苦惱, 發出來不可能要求別人也用 Sublime Text 吧.
雖然簡單一點, 合成一個 cpp 就可以了, 但自己也想攪清楚問題所在.

想請教一下, 在寫庫的時候, 把部份程式分拆成幾個 file, 應如何加進來?

以下是我的程式(還在後期 tuning 中, 但執行是沒問題的), 希望大神可幫幫忙, 為何在 Sublime Text 中一切正常的程式, 在 Arduino IDE 中會出問題.


有興趣的朋友可以嘗試 verify 庫中的範例 OLED12864_Tester.ino.
如果有 OLED 0.96 或 1.3 i2c 板的朋友, 可以直接執行.
原設定是 0.96 吋(SSD1306 i2c)的, 把 13 行的 OLED_1306i2c 改成 OLED_1106i2c, 即 OLED12864 myOLED(OLED_1106i2c, true); 就可以在 1.3 吋的OLED 執行了.
非 i2c 的版本還在編寫中, 正考慮用不同的 class , 還是像現在的在執行時用變數決定晶片, 另一個方式比較好.

如果沒有 OLED 板子的朋友, 也可以嘗 Sublime Text 2 及 Arduino IDE 試單獨 verify/compile , 也可以看到分別.

謝謝大家幫忙.

Super169 发表于 2014-4-13 14:56:40

庫可能太長了, 不易看, 做了一個完全簡化版 的 DUMMY 庫, 希望可以找出問題:

庫的 header file:
#ifndef _DUMMY_H_
#define _DUMMY_H_

#include <avr/pgmspace.h>
#include "Arduino.h"

class DUMMY {

        public:
                DUMMY();
                void setData(uint8_t data);
                uint8_t getData();

        protected:

        private:       
                uint8_t _data;

};

#endif

主庫 DUMMY.cpp:
#include <avr/pgmspace.h>
#include <DUMMY.h>
#include "DUMMY_ext.cpp"

DUMMY::DUMMY()
{
        _data = 0;
}

uint8_t DUMMY::getData() {
        return _data;
}

分拆了一個 setData 的 method 出來, 在 DUMMY_ext.ccp 內
#include <avr/pgmspace.h>
#include <DUMMY.h>

void DUMMY::setData(uint8_t data) {
        _data = data;
}

最後是一個簡單的測試程式:
#include <avr/pgmspace.h>
#include "DUMMY.h"

DUMMY d;

void setup()
{
        Serial.begin(9600);
        delay(1000);
        d.setData(123);

        Serial.println(d.getData());

}

void loop()
{

}

全部源碼的檔案:


同樣地, 在sublime 內完全沒問題, 但在 Arduino IDE 中就會出現以下 error:


DUMMY\DUMMY_ext.cpp.o: In function `DUMMY::setData(unsigned char)':
E:\Arduino\_dev\libraries\DUMMY/DUMMY_ext.cpp:4: multiple definition of `DUMMY::setData(unsigned char)'
DUMMY\DUMMY.cpp.o:/DUMMY_ext.cpp:4: first defined here
e:/arduino/_arduino-1.0.5-r2/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/ld.exe: Disabling relaxation: it will not work with multiple definitions

Super169 发表于 2014-4-13 15:15:31

找到問題了, 原來是因為我自作聰明, 根本不用 #include 也會加進來.
只是 sublime 重複再 #include 一次不會有問題, 但在 Arduino IDE 中就會看成是兩次定義.只是不明白為何加入 #ifndef 之檢測也不行.

基本測試 OK, 可以寫一點說明就放出來了.只是不知大家有沒有興趣試我寫的庫. :L

eddiewwm 发表于 2014-4-13 20:54:30

Super169 发表于 2014-4-13 15:15 static/image/common/back.gif
找到問題了, 原來是因為我自作聰明, 根本不用 #include 也會加進來.
只是 sublime 重複再 #include 一次不 ...

這麼好的分享,感謝還來不及呢!先謝了!

转角 发表于 2014-4-14 10:37:50

Super169 发表于 2014-4-13 15:15 static/image/common/back.gif
找到問題了, 原來是因為我自作聰明, 根本不用 #include 也會加進來.
只是 sublime 重複再 #include 一次不 ...

这个机制确实是挺奇怪的。
在VC中是需要手动include的,在这里难道只需要包含在工程里它就自动加载了?
如果把DUMMY类拿出来另外编译成一个LIB,这样应该就可以include了吧
刚用arduino IDE可能有些思想需要改变一下了
页: [1]
查看完整版本: 寫庫時如把程式分拆開, 如何 include 進來?