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

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

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

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

4回答

2813閲覧

エラーメッセージに納得がいかないです。

FujimuraAkira

総合スコア7

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

2クリップ

投稿2018/10/12 02:18

編集2018/10/15 00:14

前提・実現したいこと

初質問です。

組み込みLinuxでi2cドライバ開発中です。
マルチスレッドアプリで使うドライバのためmutexを使用してます。

mutex本体はi2cバスごとにlock/unlock出来るように配列になっているのですが
配列のアクセスに引数のchを使用した時、実体がないと怒られました。


if(pthread_mutex_lock(&dev_mutex[ch]) == 0){

pthread_mutex_unlock(&dev_mutex[ch]); // mutex unlock

なお、dev_mutexは別ファイルにグローバル宣言しており、
本ファイル(掲載コードのファイル)の先頭でexternして使用しています。

main.c(仮称)

// Global pthread_mutex_t dev_mutex[3];

i2c_common.c(掲載コードのファイル)

extern pthread_mutex_t dev_mutex[3]; // デバイスアクセス用mutex 0~2 I2Cバス

コード
質問1
添字を定数に変えたらエラーは消えるのですが、納得いかないです。
この時点でなぜ実体が存在しないのでしょうか?

質問2
引数のchを添字として使うスマートな方法はありませんでしょうか?

よろしくお願いします。

発生している問題・エラーメッセージ

i2c_common.c:113: `dev_mutex' に対する定義されていない参照です (同様に参照している箇所にも同じエラーが出ます)

該当のソースコード

C

1 2extern pthread_mutex_t dev_mutex[3]; // デバイスアクセス用mutex 0~2 I2Cバス 3 4/**************************************************************** 5* 関数名:i2c_write 6* 引数 :ch I2CバスNo(0~2) 7* slave_addr スレーブアドレス 8* reg レジスタアドレス 9* data データ 10* len 送信byteレングス(1 or 2) 11* 戻値 :正常 0 異常 -1 12* 説明 :スレーブデバイスに対し、I2Cライトを行う 13* データフォーマット:Start, slave_addr(w), reg, data, Stop 14****************************************************************/ 15int i2c_write(uint8_t ch, uint8_t slave_addr, uint8_t reg, uint8_t *wdata, uint8_t len) 16{ 17 int ret; 18 if(ch > 2){ 19 printf("Invalid ch : %u \r\n", ch); 20 return -1; 21 } 22 /* device mutex Ch bus*/ 23 if(pthread_mutex_lock(&dev_mutex[ch]) == 0){ 24 /* I2C open */ 25 int i2c_fd = i2c_open(ch); 26 if(i2c_fd < 0){ 27 printf("I2C write open error. ch=%u addr=0x%02x reg=0x%02x \r\n", ch, slave_addr, reg); 28 sysinfo.err.bit.state_err = true; 29 pthread_mutex_unlock(&dev_mutex[ch]); // mutex unlock 30 return -1; 31 }else{} 32 ret = ioctl(i2c_fd, I2C_SLAVE, slave_addr); 33 if(ret<0){ 34 printf("I2C write ioctl error. ch=%u addr=0x%02x reg=0x%02x \r\n", ch, slave_addr, reg); 35 close(i2c_fd); 36 syslog(LOG_ERR, "%s: Can not ioctl addr 0x%02x: %s", __func__, slave_addr, strerror(errno)); 37 sysinfo.err.bit.state_err = true; 38 pthread_mutex_unlock(&dev_mutex[ch]); // mutex unlock 39 return -1; 40 }else{} 41 if(len > I2C_BYTE_MAX){ 42 printf("I2C write size over\r\n"); 43 close(i2c_fd); 44 syslog(LOG_ERR, "%s: I2C write size over : %u", __func__, len); 45 sysinfo.err.bit.state_err = true; 46 pthread_mutex_unlock(&dev_mutex[ch]); // mutex unlock 47 return -1; 48 }else{} 49 uint8_t buf[I2C_BYTE_MAX+1] = {0}; //4byte + 1byte(アドレス分) 50 buf[0] = reg; // アドレス設定 51 for(uint8_t i=1, j=0; i<(len+1); i++,j++){ 52 buf[i] = wdata[j]; // データ設定 53 } 54 /* write */ 55 ret = write(i2c_fd, buf, len+1); //アドレス分レングス++ 56 if(ret<0){ 57 printf("I2C write write error. ch=%u addr=0x%02x reg=0x%02x \r\n", ch, slave_addr, reg); 58 close(i2c_fd); 59 sysinfo.err.bit.state_err = true; 60 pthread_mutex_unlock(&dev_mutex[ch]); // mutex unlock 61 return -1; 62 }else{} 63 /* I2C close */ 64 close(i2c_fd); 65 pthread_mutex_unlock(&dev_mutex[ch]); // mutex unlock 66 }else{ 67 printf("%s():device mutex error. I2C Ch%d\r\n", __func__, ch); 68 syslog(LOG_ERR, "%s: device mutex error I2C Ch%d", __func__, ch); 69 return -1; 70 } 71 return 0; 72}

試したこと

dev_mutex[0]の様に定数に変更した場合エラーメッセージが消えました。


2018/10/15 追記

回答ありがとうございました。
大変参考になりました。

具体的な原因は分かりませんでしたが、yumetodoさんの解答に有ったようにgetter関数を用意して回避しようと思います。
(回避策を提案頂いたのでベストアンサーとさせていただきます。)
本日をもって回答を締め切らせていただきます。

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

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

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

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

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

y_waiwai

2018/10/12 02:24

そのソースのどの行でエラーが出たんでしょうか
yohhoy

2018/10/12 05:41 編集

該当ソースコード以外での変数dev_mutexの宣言/定義文は抽出できますか?またオブジェクトファイルをnmツールで確認すると、どこでシンボル名dev_mutexが定義/利用されているかを確認できます。
guest

回答4

0

typoかリンクの方法を間違えている可能性が一番高いです

非常に稀なケースとしてコンパイラ側の仕様などで
配列の添字にuint8_tが使えない可能性があります。

size_tint等にキャストや引数リストを書き換えてみると使えるかもしれません。

投稿2018/10/12 04:24

編集2018/10/12 04:26
asm

総合スコア15147

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

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

FujimuraAkira

2018/10/12 05:02

typoと添字にuint8_tが使えない線は無さそうなので、 リンクの方法を間違えてると考えます。 その場合、具体的にどう確認したらいいのでしょうか? 当方、リンカの知識に乏しいもので、ご教授いただければありがたいのですが。 ちなみにmakeを使ってビルドしてます。 makefile 一部抜粋 CC=/gcc-linaro-5.2-2015.11-2-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc -std=c99 -D_GNU_SOURCE $(CC) -Wall -Xlinker -M=rt_manager.map -g -O0 -o $@ $(OBJS_RT) $(INCLUDE) -lpthread 見当違いな返答でしたらすみません。
guest

0

ベストアンサー

うーん、原因がつかめませんが、dev_mutex変数を外部公開するよりは、そのgetterを外部公開してあげるべきかなと。

c

1#include <stdint.h> 2pthread_mutex_t get_dev_mutex(uint8_t ch);

みたいなインターフェースのを。

投稿2018/10/12 03:03

yumetodo

総合スコア5850

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

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

FujimuraAkira

2018/10/15 00:15

具体的な回避策を提案頂いたのでBAとさせていただきます。
guest

0

こんにちは。

不思議な現象ですね。
もし、dev_mutexを定義/参照しているモジュールをライブラリ化しているようでしたら、静的ライブラリのリンク時にundefined referenceエラーが出る(gcc)の可能性もありそうです。

オブジェクト・ファイルのままリンクしている場合は、たぶん関係ないと思います。

投稿2018/10/12 08:51

Chironian

総合スコア23272

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

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

0

おそらく、ビルドのリンクの工程で出ているエラーだと思われますが、
その、 dev_mutex の定義がない、というエラーだと思われます

どこで定義されているかチェックしてみましょう

投稿2018/10/12 02:40

y_waiwai

総合スコア87774

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

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

FujimuraAkira

2018/10/12 02:49

dev_mutexの定義は別のcファイルに定義しており、 i2cドライバ用のこのファイルの先頭でexternしています。 またdev_mutex[ch]と参照している箇所をdev_mutex[0]と直すことでエラーは消えます。 これはなぜでしょうか?
y_waiwai

2018/10/12 03:22

その別のcファイルの定義をexternにして、その提示したソースのexternを外してみたらどうなるでしょうか
FujimuraAkira

2018/10/12 04:05

試したところエラーは出なくなりました。 ただ、添字が引数か定数かで実体の有無が変わるのは やはり納得がいかないです。 この現象についてなにか御存じではないでしょうか?
y_waiwai

2018/10/12 04:09

コンパイラがなにか提示されてないので、なんとも言えません いま言えることは、その別ファイルの定義が間違っている、あるいは、その定義が有効になっていなかった、ということぐらいですね
FujimuraAkira

2018/10/12 04:19

わかりました。 ありがとうございます。 ちなみにコンパイラはgccです gcc-linaro-5.2-2015.11-2-x86_64_arm-linux-gnueabihf
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問