我正在创建一个隐藏DLL文件中某些功能的C api。
由于内部的所有内容都是C ++,因此大多数函数都可以处理直接映射到API内部的指针的句柄。
为了获得这些句柄的某种程度的类型安全性,我将它们定义为:
typedef struct MyType1* MyType1Handle;
typedef struct MyType2* MyType2Handle;
我实际上并没有在任何地方定义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;
这使得可以调用想要MyType1Handle和MyType2Handle的函数,因为它们实际上是相同的类型。
我不想使用的另一种方法是这样的
typedef int MyType1Handle;
typedef int MyType2Handle;
只要int和指针具有相同的大小,这就可以正常工作,但情况并非总是如此,似乎没有万无一失的方法来获得特定于平台的指针大小整数。它也具有与void *相同的类型安全问题。
我尝试的另一种方法是这样做:
struct MyType1{};
typedef struct MyType1* MyType1Handle;
这在C中不起作用,因为空结构是无效的C代码。我当然可以用虚拟成员扩展我的结构,但似乎应该有更好的方法来做到这一点。
所以我的问题归结为:
您如何以最兼容的方式指定此类型?
答案 0 :(得分:13)
如果你看看微软如何定义它的winapi句柄(winnt.h),它实际上是这样的:
struct HWND__ { int unused; }; typedef struct HWND__ *HWND
实际上他们有一个宏:
#define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name
所以..这似乎是一种常见的做法。 不幸的是,我已经不能再提出另一个建议了 提到了,但我希望无论如何它会帮助你。
答案 1 :(得分:8)
使用不透明的结构。在C中定义库的接口时,这是一个好主意:它改进了模块化,隐藏了不必要的细节
正如杰米所说,你通过声明 - 但不是定义 - 一个结构来得到一个不透明的结构。将指向不透明结构的指针作为参数传递给库函数并将它们作为值返回是完全有效的。但是,库的用户无法创建或修改opaque结构的对象,因为它的大小和内容是未知的。
C标准库以及许多其他人已经使用这种方法,所以它应该是熟悉的。一个典型的例子是使用FILE *
:fopen()
创建并初始化结构并返回指向它的指针,fclose()
清理并释放它,所有其他i / o函数获取它们的上下文来自传递的FILE *
。
答案 2 :(得分:3)
我认为您可以声明但不定义源结构:
struct MyType1;
typedef struct MyType1 * MyType1Handle;
答案 3 :(得分:0)