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

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

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

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

Q&A

解決済

3回答

1288閲覧

C言語でソースファイル単位で、関数を公開/非公開にする方法について

GuielNo4

総合スコア88

C

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

0グッド

0クリップ

投稿2022/05/23 08:11

編集2022/05/23 09:06

前提

機能の複雑化に伴い、ソースファイルを分けるのですが、
複数人数でリポジトリを使って開発を行っているため、
「特定のソースからしか呼ばせたくない関数」の記述にどのような方法があるか調べております。

該当のソースコード

FuncA0.c

1static int counter = 0; 2void countup( void ) 3{ 4 counter += 1; 5}

FuncA1.c

1extern void countup( void ); 2static void ExecFuncA1( void ) 3{ 4 countup(); 5}

FuncA.c を 「FuncA0.c」「FuncA1.c」に分けました。
(当該コードより簡略化して記載しております。)
元々 static void countup( void ) だったものから static を外しました。

複数人数で開発している環境では
他の方のソースファイルで、extarnすれば、countup関数の呼び出しが可能です。
これを何らかの方法で、「呼び出せない」または「ビルドが通らない」ようにする方法を検討しております。

アドバイスを頂きたいこと

今、私の頭に浮かんでいる対応方法としては、
案① FuncA0.c FuncA1.c はライブラリ化する。
案② static_assert を用いて ヘッダに公開する(抑止程度ですが…)

UnpublishedFunctions.h

1#ifndef UNPUBLISHED_FUNCTIONS_H 2#define UNPUBLISHED_FUNCTIONS_H 3void countup( void ); 4static_assert( FUNC_A1_ONLY == true, ”FuncA1 only!!“ ); 5#endif

FuncA1.c

1#define FUNC_A1_ONLY ( true ) 2#include "UnpublishedFunctions.h" 3void ExecFuncA1( void ) 4{ 5 countup(); 6}

案①は、目的はある程度達成できますが、ビルドを2種類用意する必要があること。
案②は、やろうと思えば、どのソースからも呼び出すことができること。(抑止力程度…)
と、
その他になにか方法がないか、アドバイスを頂ければと思います。
宜しくお願い致します。

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

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

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

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

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

int32_t

2022/05/23 08:41

> 元々 static void countup( void ) だったものから static を外しました。 なぜ外したのでしょうか。
GuielNo4

2022/05/23 09:02 編集

質問ありがとうございます。 ビルド環境によるかもしれませんが、 FuncA0.c と FuncA1.c の関数は別物と認識されないよう外しました。 一応確認のため、外すと、 A) FuncA0.c → 参照されていません。的なワーニング B) FuncA1.c → 定義がありません。ビルドエラー となりました。
GuielNo4

2022/05/23 09:09

申し訳ありません。 FuncA1.c のサンプルコードを訂正させて頂きました。 「void ExecFuncA1( void )」→「static void ExecFuncA1( void )」 解釈が異なってしまう記述で申し訳ありません。引き続き宜しくお願い致します。
guest

回答3

0

「分ける」という作業のやり方を間違っている,という話に見えます.

「特定のソースからしか呼ばせたくない関数」

を,元々はそのソース内に static 関数として書いていた,という話なのでしょうから,そこはそのままにしておくべきでは.


どうしても「ファイル」という単位で分けたいというのであれば,

FuncA0.c_

1//※このファイルはコンパイル対象としない 2static void countup( void ){ ... } //static関数の実装記述

FuncA1.c

1#include "FuncA0.c_"

とかしておけばまぁ…(こんなことやる意味あるのか?ってのは別として)

投稿2022/05/23 08:42

編集2022/05/23 08:45
fana

総合スコア11652

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

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

GuielNo4

2022/05/24 04:15

アドバイスありがとうございます。 ヘッダではないものインクルードする的な発想がありませんでした。 今後、別の何かに利用したいと思います。 回答ありがとうございました。
fana

2022/05/24 06:31 編集

(後半の話はわりとネタ気味なので変に利用できるとか考えない方が) 重要なのは前半です. 「(そこは)分けない」のが正解ちゃうんかと. 意味的に内部リンケージでなければならないものを翻訳単位の外部に追い出し→それで生じた齟齬を何かしらの小手先の技でごまかそう, みたいな作業を実施しようと考えていること自体がそもそも間違っている.
guest

0

標準のC言語の範囲内で完全に使用を防ぐには、countup() を FuncA1.c に移動して static を付ける以外の手段はないと思います。

案①について : FuncA*.c を1つの動的ライブラリ(*.dll *.so *.dylib)にすると、ライブラリから公開するシンボルを選べるので実現できます。静的ライブラリでは宣言を書けば使えるので完全に防ぐことはできません。

案②に似たような話ですが、FuncA*.c を1つのコンポーネントとして考えて、それらをコンパイルするときにはビルドルールで IN_FUNC_A などのマクロを定義するようにします。IN_FUNC_A が定義されているときだけ countup() をヘッダで宣言すれば意図は伝わるんじゃないかと思います。

私が仕事で関わったプロジェクトだと、どのディレクトリからどのファイルを #include できるかできないかのルールが定義してあって、コードレビューの前処理としてそのルールのチェックが行われていました。この場合、countup() を宣言するヘッダは FuncA*.c があるディレクトリ以外からの利用を禁止すればいいですね。

C++ だと passkey pattern などで呼び出し元クラスを制限できます。

投稿2022/05/23 22:49

int32_t

総合スコア20825

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

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

GuielNo4

2022/05/24 04:15

アドバイスありがとうございます。 やはりバグを出さないために検討しているので、 頂いております回答より、 「ビルドルール」「コードレビュー」で対応することも 検討すべきだと思いました。 回答ありがとうございました。
guest

0

ベストアンサー

「特定のソースからしか呼ばせたくない関数」の記述にどのような方法があるか調べております。

無理です。あきらめよう

投稿2022/05/23 09:25

編集2022/05/23 09:26
y_waiwai

総合スコア87747

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

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

GuielNo4

2022/05/24 04:15

アドバイスありがとうございます。 ないかもしれないものを、すっと探し続けるよりは 先達に「ない」とアドバイス貰ったほうがいいタイミングだったかもしれません。 回答ありがとうございました。
y_waiwai

2022/05/24 04:52

まあ、せいぜいライブラリにして、ソースを公開しない、必要なところ以外には仕様を公開しない、とすることでしょうね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問