質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

0回答

1566閲覧

gcc(7.3.0)にて、関数をオーバーライドしたい

thkana

総合スコア7703

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

1クリップ

投稿2020/12/12 01:17

###やりたいことサンプル:

C++

1int func(){//a (ライブラリ中で定義) 2 return 1; 3} 4 5int func(){//b (ユーザーソースで定義) 6 return 2; 7} 8 9int main(){ 10 func();//bが呼び出されるようにしたい 11 return 0; 12}

aの記述はいじらず、b側(ソース中の記述)だけでmainからbが呼び出されるように出来ないか。
__attribute__((weak))の反対の機能を持つ__attribute__((strong)) (仮称)みたいなのがあって強制的にオーバーライド出来たりすると嬉しいのですけれど、見つけられていません。
一般的にはリンカの--wrapオブションで...という手段もあるようですが、特殊事情(下記)で使えませんでした。

###実際の状況:
Arduino IDE(1.8.13 gcc(7.3.0)/C++ ターゲットArduino UNO Win10)において、シリアル通信でハードウェアフロー(の一部、CTS)を実現したい。そのため、送信の割り込み処理を置き換えたい。

しかし、Arduinoのライブラリでは、割り込みハンドラはベタに定義されていて、ユーザー側で送信割り込みハンドラを設定しようとすると多重定義でリンク時エラーになる。

Arduino

1#include "mySerial.h" 2volatile bool irq=false; 3void setup() { 4 MySerial.begin(115200); 5 MySerial.println("Hello, world.\n"); 6 delay(10); 7 MySerial.println(irq); //以下の割り込みが実行されれば1 8} 9 10void loop() { 11} 12 13ISR(USART_UDRE_vect) 14{ 15 irq=true; 16 MySerial._tx_udr_empty_irq();//元の割り込みと同じ処理 17}

mySerial.h

C++

1#pragma once 2#include <Arduino.h> 3#include <HardwareSerial.h> 4#include <HardwareSerial_private.h> 5class mySerial: public HardwareSerial { 6 using HardwareSerial::HardwareSerial; 7}; 8mySerial MySerial(&UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UCSR0C, &UDR0);

ISRマクロの定義(ライブラリ内)

C++

1# define ISR(vector, ...) \ 2 extern "C" void vector (void) __attribute__ ((signal,__INTR_ATTRS)) __VA_ARGS__; \ 3 void vector (void)

エラーメッセージ

Text

1HardwareSerial0.cpp.o (symbol from plugin): In function `Serial': 2(.text+0x0): multiple definition of `__vector_19'

###[試行1]ライブラリを書き換える
hardware/arduino/avr/cores中のHardwareSerial.cpp中の
ISR(USART_UDRE_vect)
ISR(USART_UDRE_vect,__attribute__((weak)))とする
これにより、上記ソースのビルドが正常終了し、

Text

1Hello, world. 21

がSerialに出力される。つまり、オーバーライド自体は出来ていて、普通に使う分には従来動作も確保できるので悪くはない。が、やはりライブラリを書き換えるというのは邪道な感。また、Arduino IDEのインストールの仕方によって?ライブラリの場所がインストールディレクトリになったりUsers/ユーザー/AppData/Local/Arudino15以下になったりする様子。自分で環境を変えた時の再現も他人に伝えるのも面倒。

###[試行2]リンカオプション --wrap を使えないか検討
割り込みベクタ名が特別に認識されるようで(__attribute__((signal))の作用?) __wrap_の関数名とすると割り込みハンドラとして機能しない様子。NG。まぁ、こちらもIDEのコンパイルオプションファイルをいじらなきゃいけなくなるので、たとえ出来ても使いたくない方法ではあるのですが。

なにか手はありますでしょうか...

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

thkana

2020/12/14 12:40

yohhoyさん 情報ありがとうございます。 自分でmakeを作る環境なら使える技なんでしょうが、Arduino IDEはその辺のライブラリはclean buildの場合はソースから生成してくれちゃうし(なので、予め手動で変更しておく手が使えない)、(多分)makeにあまり手を入れられないしでちょっと難しそうですね。 一応、他人にポンと「使ってね」と渡せることを目指したいので... Arduinoが「お手軽に電子工作の部品としてマイコンを使いましょう」というようなコンセプトのプロジェクトなので(と私は思っている)、あまり突っ込んだことをやろうというほうがナンなのかも知れません...
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問