-2

api.h で

typedef void* hidden_my_type;
void do_something(my_type x);

core.c で

struct _my_type
{
    int a;
}

void do_something(hidden_my_type void_x)
{
   struct *_my_type x = void_x;  /*Don't understand is that correct way to do, as I'm getting segmentation fault error */
   printf("Value: %d\n", x->a);
}

別の方法として、

struct *_my_type x = (struct _my_type *)malloc(sizeof(struct _my_type));
void_x = x
printf(Value: %d\n", x->a);

しかし、それでも seg-fault エラーが発生します。


さて、これが void* の問題です....

例えばcore.cで

void init_my_type(hidden_my_type a)
{
   my_type *the_a = malloc(...);
   a = the_a   // <<<<<<<<<<<<<<<<<<<<<<<<<<<< is this correct?! a is void* and the_a // is original type
   pthread_cond_init(&the_a->...);
    .. (in short any other methods for init ..)
}
void my_type_destroy(my_hidden_type x)
{
    my_type *the_x = x;
    pthread_detroy(&the_x-> ...);
}

main.c で

test()
{
   my_hidden_type x;
   init_my_type(x);
   .... 
   my_type_detroy(x);
}

これ自体は失敗するはずです。main.c テスト関数のように、x は void* です ... init は割り当てますが、destroy では再び void* を渡します .. これは何でもかまいません!

編集(私のために解決)

api.h で

typedef void* hidden_my_type;
void do_something(my_type x);

core.c で

 struct _my_type
    {
        int a;
    }


 void init_hidden_type(hidden_my_type void_p_my_type)
    {
        struct _my_type *real_my_type = (struct _my_type *)malloc(sizeof(struct _my_type));
        //--- Do init for your type ---
        void_p_my_type = real_my_type;
    }


 void do_something(hidden_my_type void_x)
    {
       struct *_my_type x = void_x; 
       printf("Value: %d\n", x->a);
    }
4

2 に答える 2

1

バージョン0—質問のコードに対する批評

投稿されたコードはコンパイルされません。

api.h

typedef void* hidden_my_type;
void do_something(my_type x);

これは、に渡されるを定義しますhidden_my_typeが、を定義しません。おそらく、あなたは意図していました:my_typedo_something()

typedef void *my_type;
void do_something(my_type x);

core.c

struct _my_type
{
    int a;
}

以下でも説明するように、構造体の定義の後にセミコロンがありません。

void do_something(hidden_my_type void_x)
{
   struct *_my_type x = void_x;
   printf("Value: %d\n", x->a);
}

hidden_my_type再びvsのmy_type問題があります。あなたは*それが行くことができないポインタのを持っています。の後に行く必要がありstruct _my_typeます。あなたはおそらく次のようなことを意図していました:

void do_something(my_type void_x)
{
   struct _my_type *x = void_x;
   printf("Value: %d\n", x->a);
}

これは構文的に正しいようになりました(私は思います;私は実際にコンパイラーを通過して実行していません)。あなたはそれがどのように使われるかを示していません。実際、ユーザーコードには有効な構造体へのポインターを生成する方法がないため、このコードを安全に使用する方法はありません。

テストコード(表示されていません—テストコードを表示しませんか)は次のようになります。

#include "api.h"

int main(void)
{
    my_type x = 0;
    do_something(x);
    return 0;
}

= 0または、イニシャライザが配置されていない可能性があります。いずれにせよ、コードは正常に機能できず、コアダンプはほぼ​​避けられません。構造をユーザーから隠すときは、構造を有効な(ポインターとして)取得するためのメカニズムをユーザーに提供する必要がありますが、それは行っていません。

バージョン1

これは、タイプセーフに近いため、これを行うためのより良い方法です。

api.hバージョン1

typedef struct _my_type *my_type;
void do_something(my_type x);

core.cバージョン1

#include "api.h"
struct _my_type
{
    int a;
};

追加されたセミコロンとapi.hファイルのインクルードに注意してください。

void do_something(my_type x)
{
    // Now you don't have to do casting here!
    //struct *_my_type x = void_x;  /*Don't understand is that correct way to do, as I'm getting segmentation fault error */
    printf("Value: %d\n", x->a);
}

バージョン2

実際、ポインタを隠すことの知恵について議論することができます。私はそうしないことを望みます:

api.hバージョン2

#ifndef API_H_INCLUDED
#define API_H_INCLUDED

typedef struct my_type my_type;
extern void     do_something(my_type *x);
extern my_type *my_type_initializer(void);
extern void     my_type_release(my_type *x);

#endif /* API_H_INCLUDED */

core.cバージョン2

#include "api.h"
#include <stdio.h>
#include <stdlib.h>

struct my_type
{
    int a;
};

void do_something(my_type *x)
{
    printf("Value: %d\n", x->a);
}

my_type *my_type_initializer(void)
{
    my_type *x = malloc(sizeof(*x));
    x->a = 57;  // More plausibly, this would be 0
    return x;
}

void my_type_release(my_type *x)
{
    free(x);
}

main.c

#include "api.h"

int main(void)
{
    my_type *x = my_type_initializer();
    do_something(x);
    my_type_release(x);
    return 0;
}

それは素晴らしくてきれいです。もちろん、ユーザーはstruct my_type(それへのポインターのみ)を割り当てることはできないため、ユーザーに構造を割り当てるための関数が必要です。標準CライブラリとFILE型を考え、型を操作するfopen()ために割り当て、fclose()解放などを行います。fprintf()は、のアナログとして、のアナログとして、およびのアナログとしてmy_type_initializer()機能しています。fopen()my_type_release()fclose()do_something()fprintf()

于 2012-04-17T00:35:19.060 に答える
0

ジョナサン、あなたは私を打ち負かして答えましたが、これも役立つかもしれません。ここにapi.cは、(プライベート)実装が含まれており、api.hなどの他のコードで使用されるインターフェイスを提供しますmain.c

// main.c: uses only the public interface to the private code
#include "api.h"

int main(int argc, char *argv[]) {
  void *foo;

  foo = create_foo("five", 5);
  print_foo(foo);
  delete_foo(foo);
}
// EOF main.c


// api.h: the public interface
#ifndef _api_h_
#define _api_h_
void *create_foo(char *name, int number);
void print_foo(void *foo);
void delete_foo(void *foo);
#endif // _api_h_


// api.c: the private implementation
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// The real structure is private to the implementation.
typedef struct {
        char name[20];
        int number;
} real_struct;

// Create a new structure, initialize, return as ptr-to-void.
void *create_foo(char *name, int number) {
  real_struct *s = malloc(sizeof(real_struct));
  strcpy(s->name, name);
  s->number = number;
  return (void *) s;
}

// Print the data.
void print_foo(void *foo) {
  real_struct *s = (real_struct *) foo;
  printf("name: %s, number: %d\n", s->name, s->number);
}

// Release the memory.
void delete_foo(void *foo) {
  free(foo);
}
// EOF api.c

このコードはコンパイルして実行する必要があります。

$ gcc -o foo main.c api.c
$ ./foo

name: five, number: 5
于 2012-04-17T01:01:10.337 に答える