C接口中句柄的正确类型

Las*_*lan 15 c c++ api

我正在创建一个隐藏DLL文件中的某些功能的C api.

由于内部的所有内容都是C++,因此大多数函数都可以处理直接映射到API内部的指针的句柄.

为了获得这些句柄的某种程度的类型安全性,我将它们定义为:

typedef struct MyType1* MyType1Handle;
typedef struct MyType2* MyType2Handle;
Run Code Online (Sandbox Code Playgroud)

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

我的问题是,当我在Visual Studio的clr项目中使用我的库时,我得到了这个 warning: unresolved typeref token (token) for 'type'; image may not run.

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

它起作用并没什么大不了的,但看起来不专业.

我不喜欢使用void*:

typedef void* MyType1Handle;
typedef void* MyType2Handle;
Run Code Online (Sandbox Code Playgroud)

这使得可以调用想要MyType1Handle和MyType2Handle的函数,因为它们实际上是相同的类型.

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

typedef int MyType1Handle;
typedef int MyType2Handle;
Run Code Online (Sandbox Code Playgroud)

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

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

struct MyType1{};
typedef struct MyType1* MyType1Handle;
Run Code Online (Sandbox Code Playgroud)

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

所以我的问题归结为:

你如何以最兼容的方式指定这种类型?

lx.*_*lx. 14

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

struct HWND__ { int unused; }; typedef struct HWND__ *HWND
Run Code Online (Sandbox Code Playgroud)

事实上,他们有一个宏:

#define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name
Run Code Online (Sandbox Code Playgroud)

所以..这似乎是一种常见的做法.不幸的是,我不能提出另一个建议,除了你已经提到过的这个建议,但我希望无论如何它对你有所帮助.


小智 8

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

正如JamieH所说,通过声明 - 但不是定义 - 结构来获得不透明的结构.将指向不透明结构的指针作为参数传递给库函数并将它们作为值返回是完全有效的.然而,库的用户无法创建或修改opaque结构的对象,因为它的大小和内容是未知的.

C标准库和许多其他人已经使用这种方法,因此它应该是熟悉的.一个典型的例子是使用FILE *:fopen()创建并初始化结构并返回指向它的指针,fclose()清理并释放它,所有其他i/o函数从传入中获取它们的上下文FILE *.