或许,我不应该施展。这就是我正在做的事情:
我正在编写一段代码,将Linux设备驱动程序链接到更高级别的库。该库的作者使用void *
(通过typedef
的新名称)将句柄存储到描述通信通道的特定于实现的对象。
我想与库连接的驱动程序使用int
来存储其通道的句柄(因为它们是调用open()
返回的文件描述符)。所以,在我的代码中,我从库中传入void *
,需要使用int
从驱动程序调用内容,反之亦然。 I. e。:
// somewhere in the library ...
typedef void* CAN_HANDLE;
// ... in my code
CAN_HANDLE canOpen_driver(s_BOARD *board)
{
int fd;
// ...
fd = open(busname, O_RDWR);
// ...
return (CAN_HANDLE) fd; // <-- not safe, especially not when converting back.
}
其他人编写的适配器实际上存储了一些结构等等,只是在指针之间进行转换,因此不会出现大小问题。在我的情况下,我真的不想像操作系统那样管理文件描述符。
在我的电脑上,我认为指针大于int
,所以我可以用它来解决这个问题,但代码也会进入嵌入式系统,而且我没有足够的经验对这些机器上的类型大小做出任何假设。
答案 0 :(得分:3)
编辑:当然你不需要一个结构,你可以只为普通的int分配内存。
CAN_HANDLE canOpen_driver(s_BOARD *board)
{
int *fd = malloc(sizeof(int));
if (fd)
{
// ...
*fd = open(busname, O_RDWR);
// ...
return (CAN_HANDLE) fd;
}
// failure
return NULL;
}
这假设有一个匹配的清理呼叫。类似的东西:
void canClose_driver(CAN_HANDLE handle)
{
int *fd = handle;
free(fd);
}
答案 1 :(得分:2)
根据架构,您可能会侥幸逃脱。如果我理解正确,驱动程序实际上从未使用您提供给它的void *。它只是存储它以便稍后将其传递回您的代码。
基于这个假设,只要sizeof(void *)&gt; = sizeof(int),就可以安全地在这些类型之间进行转换,因为你确定它实际上是一个int。
如果你不能保证大小条件,或者不想依赖hack,你应该为int分配内存并返回该内存的地址。例如,您可以使用malloc()或在固定大小的数组中分配int。缺点是,当不再需要时,您将需要释放该内存。我想,当不再需要数据结构时,驱动程序会发出某种通知,告知您的代码。
答案 2 :(得分:0)
通常在嵌入式系统上,以下CPU型号最常见:
Data bus Address bus
8 bit 16 bit
8 bit 16+8 bit (banking)
16 bit 16 bit
16 bit 16+8 bit (banking)
32 bit 32 bit
通常,地址总线将始终> =数据总线。我想不出任何数据总线大于地址总线的CPU。
这是一个有点肮脏的技巧,可能会或可能不会解决问题:
typedef union
{
CAN_HANDLE handle;
long value;
} CAN_HANDLE_t;
这应该是相当便携的,即使你可能必须使这个联盟适应特定的系统(远指针等)。