0

私にはプロジェクトがあり、それがどのように機能するかを制御する、頻繁に変更されるプリプロセッサがいくつかある場合があり#defineます-例:

void myfunction(int num, mystruct* content) {
    doSomethingTo(content);
    //...
    #ifdef FEATURE_X
    feature_x(content);
    #endif
}

これは問題なく動作しますが、毎回再コンパイルする必要があるため、「毎回再コンパイルする必要があるもの」ファイルにあります。代わりに [静的] ライブラリにプッシュしたいと思います。私はそれがどのように呼び出されるかを変更しても大丈夫です(すでにピッキングのための関数ポインタを持っていますmyFunction)ので、それを

void myfunction(int num, mystruct* content) {
    doSomethingTo(content);
    //...
}
void myfunction_featureX(int num, mystruct* content) {
    doSomethingTo(content);
    //...
    feature_x(content);
}

これをいくつかの場所で行う必要があるため、それぞれに別のライブラリ ( があるものとないもの-D FEATURE_X) を使用することは、受け入れられるオプションではありません。コピー/貼り付けでそれを行うこともできますが、コードの再利用が発生し、一方のコピーではバグが修正されても、他方では修正されないというリスクが伴います。

4

3 に答える 3

1

代わりに関数テーブルに myfeature_x を入れると役に立ちますか?

#include <stdio.h>
#include <string.h>

typedef struct {
  int x,y;
} mystruct;

typedef void (*fn_ptr)(mystruct* content);
fn_ptr vtable[10];
#define FEATURE_X_INDEX 0

void feature_x(mystruct *content)
{
  printf("y: %d\n", content->y);
}

void myfunction(int num, mystruct* content) {
  printf("x: %d\n", content->x);

  //...
  if (vtable[FEATURE_X_INDEX]) {
    vtable[FEATURE_X_INDEX](content);
  }
}

int main(void)
{
  bzero(vtable, sizeof(vtable));
  mystruct s;
  s.x = 1;
  s.y = 2;
  myfunction(0, &s);
  if (1) {
    //Of course you'd use a more sensible condition.
    vtable[FEATURE_X_INDEX] = feature_x;
  }
  myfunction(0, &s);
  return 0;
}

出力:

x: 1
x: 1
y: 2

次に、その機能を使用しない場合は仮想関数テーブルにNULLs を入力し、使用する場合は関数ポインターを入力するだけです。これは、どこからでも実行できます-たとえば、静的ライブラリ..またはfeature_x、動的ライブラリにコンパイルし、実行時にロードし、ロードが成功した場合は関数テーブルにデータを入力し、動的にリンクされたライブラリがアンロードされたときにテーブルをクリアします.

これが Jonathan Leffler の方法よりも実際に得られる唯一の利点は、feature_x のコードを他のコードと同じバイナリに実際にリンクする必要がないことだと思います。機能をオンまたはオフにするためのランタイム スイッチだけが必要な場合は、ifJonathan Leffler が提案したように、簡単なステートメントでうまくいくはずです。(ちなみに、ifここにもあります-関数テーブルの内容をチェックします:))

于 2013-02-02T23:49:13.193 に答える
1

関数の featureX バージョンがメインライン関数を呼び出すようにします。あなたの例でmyfunction_featureXは、呼び出しmyfunctionてから独自のことを行います。

于 2013-02-02T23:42:26.880 に答える
1

確かに、これは機能 X のアクティブ化をコンパイル時の問題から実行時の問題に変更するポイントです。

void myfunction(int num, mystruct* content)
{
    doSomethingTo(content);
    //...
    if (FeatureX_Enabled())
        feature_x(content);
}

テストはFeatureX_Enabled()完全な関数である場合もあれば、関数の外部で定義された適切な範囲の変数 (ファイル内の静的変数または外部変数) を単にテストする場合もあります。これにより、関数ポインタをいじる必要がなくなります。今呼び出されているのと同じ関数です。関数ポインターのテーブルを変更することは、単一の変数を変更することと同じです。関数の動作を変更するために、関数の外部に格納されているものの値を変更する必要があります。

于 2013-02-03T00:02:50.433 に答える