代码之家  ›  专栏  ›  技术社区  ›  Laserallan

C接口中句柄的正确类型

  •  14
  • Laserallan  · 技术社区  · 17 年前

    因为所有的东西都是C++,所以大多数函数都是针对直接映射到API内部的指针的句柄。

    为了使这些手柄具有某种程度的类型安全性,我将其定义如下:

    typedef struct MyType1* MyType1Handle;
    typedef struct MyType2* MyType2Handle;
    

    实际上,我没有在任何地方定义MyType1或MyType2,因为我只将它们用作指针,并在api内部对实际指针类型进行类型转换。

    warning: unresolved typeref token (token) for 'type'; image may not run.

    http://msdn.microsoft.com/en-us/library/h8027ys9(VS.80).aspx

    typedef void* MyType1Handle;
    typedef void* MyType2Handle;
    

    这使得调用需要MyType1Handle和MyType2Handle的函数成为可能,因为它们实际上是相同的类型。

    我不想使用的另一种方法是这样的

    typedef int MyType1Handle;
    typedef int MyType2Handle;
    

    只要int和指针具有相同的大小,这就可以正常工作,但情况并非总是如此,似乎没有简单的方法可以获得特定于平台的指针大小的整数。它也有与void*相同类型的安全问题。

    我尝试的另一种方法是这样做:

    struct MyType1{};
    typedef struct MyType1* MyType1Handle;
    

    这在C中不起作用,因为空结构是无效的C代码。我当然可以用一个虚拟成员来扩展我的结构,但似乎应该有更好的方法来实现这一点。

    因此,我的问题归结为:

    您通常如何以最兼容的方式指定此类类型?

    4 回复  |  直到 17 年前
        1
  •  14
  •   lx.    17 年前

    如果您看一下Microsoft如何定义其winapi句柄(winnt.h),它实际上是这样的:

    struct HWND__ { int unused; }; typedef struct HWND__ *HWND
    

    事实上,他们有一个宏:

    #define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name
    

    所以这似乎是一种常见的做法。 不幸的是,除了你已经提出的这个建议,我不能再提其他建议了 提到过,但我希望它能帮助你。

        2
  •  8
  •   Wuggy    17 年前

    使用不透明结构。在许多情况下,在C中定义库的接口时,这是一个好主意:它提高了模块性,隐藏了不必要的细节

    C标准库和许多其他库已经使用了这种方法,因此应该对它很熟悉。cannonical的例子是使用 FILE * : fopen() fclose() 清理并释放它,所有其他i/o函数从传入的 .

        3
  •  3
  •   Community Mohan Dere    6 年前

    我认为您可以只声明但不定义源结构:

    typedef结构MyType1*MyType1Handle;