2

それぞれの信号を切り替えることができるシナリオに関連するプロパティに基づいて切り替えられるハードウェア信号がいくつかあります。問題は、シナリオを定義するシグナルとプロパティ、3つすべてが変更される可能性があることです。SignalManager信号の作成を処理するものがあり、SignalPropertiesData特定の構造SignalPropertiesDataManagerを関連付けるものSignalScenarioがあり、これはすべて、によって任意のタイプの信号用に特別に作成される、モジュラーフレームワークベースの設計の観点から考える必要がありSignalManagerます。Cプログラミングパラダイムのパブリックインターフェイス、プライベートデータをフォローしたいと思います。

私のジレンマは、型安全性とこの種の問題に関しては一般的にCです。唯一の解決策は、型安全性を失い、すべての型のデータに「void」を使用することです。広大なオープンソースの海にあるコードやコンポーネントを教えてください。これは、この問題の正しいリファレンスとして役立ちます。

signal_manager.h:

#ifdef _SIGNAL_MANAGER_H
#define _SIGNAL_MANAGER_H

int createSignal(SignalDescPtr signalDescPtr);

int destroySignal();

typedef struct SignalDesc* SignalDescPtr;

#endif

signal_manager.c:

#include "signal_manager.h"

typedef struct {
  char* signalName;
  unsigned int signalId;
  SignalPropertiesDataPtr signalProperties;
} SignalDesc;

signal_properties_data.h:

#ifdef _SIGNAL_PROPERTIES_DATA
#define _SIGNAL_PROPERTIES_DATA

typedef enum {
  SIGNAL_DATA_INT_TYPE,
  SIGNAL_DATA_UNSIGNED_INT_TYPE,
  SIGNAL_DATA_FLOAT_TYPE,
     :
  SIGNAL_DATA_UNSPECIFIED_BASIC_TYPE
} eSignalBasicType;

typedef enum {
  SIGNAL_DATA_LIST_ARRAY_TYPE,
  SIGNAL_DATA_LIST_ADT_TYPE,
   :
   :
  SIGNAL_DATA_LIST_UNSPECIFIED_TYPE
} eSignalComplexType

typdef  union {
  eSignalBasicType signalBasicType;
  eSignalComplexType signalComplexType;
} eSignalType;

typedef struct {
  eSignalType signalType;
  unsigned int signalDataLen;
} SignalDataValueType;    

typedef SignalPropertiesData* SignalPropertiesDataPtr;

result_t setSignalType(..);
result_ getSignalType(..);
result_t setSignalData(..);
result_t getSignalData(..);
result_t setSignalDataLen(..);
result_t getSignalDataLen(..);

#endif

signal_properties_data.c:

#include "signal_properties_data.h"

typdef struct {
  SignalDataValueType signalPropertiesDataType;
  void* signalPropertiesDataValue;
} SignalPropertiesData;

signal_properties_data_mgr.h:

#ifdef _SIGNAL_PROPERTIES_DATA_MGR_H
#define _SIGNAL_PROPERTIES_DATA_MGR_H

#include "signal_properties_data.h"
#include "signal_scenario.h"

typedef SignalScenarioDesc* SignalScenarioDescPtr;

result_t createSignalPropertiesData(SignalPropertiesDataPtr *signalPropDataPtr, eSignalType desiredSignalType);

result_t freeSignalPropertiesData(..);

result_t associateSignalToggleScenario(SignalPropertiesDataPtr *signalPropDataPtr, SignalScenPtr signalScenPtr);

result_t disassociateSignalToggleScenario(SignalPropertiesDataPtr *signalPropDataPtr, SignalScenarioDescPtr signalScenPtr);

#endif 

signal_properties_data_mgr.c:

#include "signal_properties_data_mgr.h"

typedef struct {
  toggleFuncPtr fptr;
} SignalScenarioDesc;
4

2 に答える 2

0

に行くのは避けてくださいvoid *。プロトタイプの利点を失い、必要ではありませんが、

これは C なので、次のように記述します。signalmanager.h

#ifndef SIGNAL_MANAGER_H_INCLUDED
#define SIGNAL_MANAGER_H_INCLUDED

typedef struct SignalDesc* SignalDescPtr;

int createSignal(SignalDescPtr signalDescPtr);

int destroySignal(void);

#endif

変更点:

  1. Critical : イディオムは#ifndef MACRO / #define MACRO / #endif. あなたが使用#ifdefしたものは機能しません。
  2. 使用する前に typedef を配置します。
  3. プロトタイプ(void)に makeを明示的に追加します。destroySignal(void)あなたのバージョンは単に「destroySignal()を返す関数がありますintが、指定されていない(ただし可変個ではない)引数リストを取ります」と言っています。
  4. ヘッダー保護ガードに予約済みの名前空間 (先頭のアンダースコア、大文字) を使用しないでください。

データ型 typedef でポインターを非表示にしたくないので、おそらく次のように記述します。

#ifndef SIGNAL_MANAGER_H_INCLUDED
#define SIGNAL_MANAGER_H_INCLUDED

typedef struct SignalDesc SignalDesc;

extern int createSignal(SignalDesc *sigdesc);

extern int destroySignal(void);

#endif /* SIGNAL_MANAGER_H_INCLUDED */

create と destroy へのインターフェイスが正しいかどうかはわかりませんが、それは別の話題です。私は通常、インターフェースがより似ていることを期待しています:

extern SignalDesc *createSignal(const char *name, int signum);
extern void destroySignal(SignalDesc *sigdesc);

次に、実装ファイルsignal_manager.cは構造タイプを定義して使用します。外部インターフェイスは、ポインターを操作する関数を介して行われます。

#include "signal_manager.h"
#include "signal_properties_data.h"

struct SignalDesc
{
    char                 *signalName;
    unsigned int          signalId;
    SignalPropertiesData *signalProperties;
};

同様のsignal_properties_data.hクリーンアップが必要です。

#ifndef SIGNAL_PROPERTIES_DATA_H_INCLUDED
#define SIGNAL_PROPERTIES_DATA_H_INCLUDED

typedef enum {
  SIGNAL_DATA_INT_TYPE,
  SIGNAL_DATA_UNSIGNED_INT_TYPE,
  SIGNAL_DATA_FLOAT_TYPE,
     :
  SIGNAL_DATA_UNSPECIFIED_BASIC_TYPE
} eSignalBasicType;

typedef enum {
  SIGNAL_DATA_LIST_ARRAY_TYPE,
  SIGNAL_DATA_LIST_ADT_TYPE,
   :
   :
  SIGNAL_DATA_LIST_UNSPECIFIED_TYPE
} eSignalComplexType

typdef  union {
  eSignalBasicType signalBasicType;
  eSignalComplexType signalComplexType;
} eSignalType;

typedef struct {
  eSignalType signalType;
  unsigned int signalDataLen;
} SignalDataValueType;

/* Huge hole in types here - or is SignalValueDataType what you're after? */
typedef struct SignalPropertiesData SignalPropertiesData;

result_t setSignalType(..);
result_t getSignalType(..);
result_t setSignalData(..);
result_t getSignalData(..);
result_t setSignalDataLen(..);
result_t getSignalDataLen(..);

#endif  /* SIGNAL_PROPERTIES_DATA_H_INCLUDED */

この改訂されたヘッダーはまだ自己完結型ではありません。を定義していないため、定義しresult_tているヘッダーを含める必要があります。Cでは有効ではないため、関数呼び出しの...表記は「この質問では指定したくない」であると思います。省略記号を指定する前に、既知の型の引数が 1 つ必要です。

ヘッダーの関数からは、ヘッダーのユーザーがヘッダーで定義されている型について知る必要がある理由が明確ではありません。ヘッダーは、共有されるリソースと考えてください。これは、ファイル (またはファイルの小さなセット) への外部インターフェイスに「属する」か、または説明します。コードによって提供される機能を使用するために必要な最小限のデータをユーザーに提供しますが、最小限のデータしか提供しません。ファシリティを実装する一連のファイルには、それらの間で共有するためのプライベート ヘッダーと、他のコード (「顧客」コードまたは「コンシューマー」コード) が使用するパブリック ヘッダーが必要になることがあります。

不透明な型の鍵は、構造体型へのポインタを使用できるようにするために、消費者が構造体の内部の詳細を知る必要がないことです ( C 標準のどの部分を参照して、このコードをコンパイルできますか?C 標準はありますか?このヘッダーには 1 つまたは 2 つのstruct uperms_entryタイプがあると考えてください?およびCでヘッダー ファイルを構造化する方法を参照してください)。

于 2012-10-21T01:20:38.173 に答える
0

あなたのニーズが何であるかを完全に理解しているかどうかはわかりませんが、参考実装としてWIN32 ハンドルを参照できると思います。

簡単な例として、次のようなカスタム ハンドルを定義できるマクロを定義します。

/* example.h */

#ifndef _EXAMPLE_H
#define _EXAMPLE_H

/* Define macro */
#define DECLARE_HANDLE(HandleName) typedef struct HandleName##Tag * HandleName

/* Declare some handles */
DECLARE_HANDLE(SomeHandle);
DECLARE_HANDLE(SomeOtherHandle);

#endif /* _EXAMPLE_H */

/* example.c */

#include "example.h"

struct SomeHandleTag {
    int foo;
};

struct SomeOtherHandleTag {
    int foo;
};
于 2012-10-21T01:22:04.313 に答える