简体   繁体   English

如何将 volatile int** 转换为 void**

[英]How to cast volatile int** to void**

I have this old C - code that my compiler is warning me about (old C-style cast).我有这个旧的 C - 我的编译器警告我的代码(旧的 C 风格转换)。

volatile uint32_t* map;
void** argForSomeAPIfunction = (void**)↦

How can I convert this to C++ cast style?如何将其转换为 C++ 类型转换? I need to convert volatile uint32_t** to void**.我需要将 volatile uint32_t** 转换为 void**。

The reason why I need this is that there is a closed-source vendor API that expects me to pass a void** pointer.我需要这个的原因是有一个闭源供应商 API 期望我传递一个 void** 指针。 I cannot change that function signature.我无法更改该函数签名。 On the other hand, the vendor told me that I can access this map of registers, that are always 32-bit, using a pointer to uint32_t, and he provided me the working example in C-style, that used (void**)& .另一方面,供应商告诉我,我可以使用指向 uint32_t 的指针访问这个始终为 32 位的寄存器映射,他为我提供了 C 风格的工作示例,使用(void**)& I tried this C-example and it's working fine.我试过这个 C-example,它工作正常。

Side note: This vendor API communicates with a PCIe card, via a custom kernel module.旁注:此供应商 API 通过自定义内核模块与 PCIe 卡通信。 There are two options two read the internal memory of the PCIe card, using a safe API function that uses "ioctl" and built-in checks, or using an unsupervised access to this 32-bit register map, that is initialized by calling to API::InitializeRegisterMap((void**)&map);有两个选项 2 读取 PCIe 卡的内部存储器,使用使用“ioctl”和内置检查的安全 API 函数,或者使用对这个 32 位寄存器映射的无监督访问,即通过调用API::InitializeRegisterMap((void**)&map);初始化API::InitializeRegisterMap((void**)&map); . . This is done only once, at the very beginning of the program.这仅在程序开始时执行一次。 After that, I access directly the memory using map[offset] , where offset goes in steps of 4 bytes, instead of the supervised function API::ReadRegister(offset) that in some cases is slower and critically delays the data acquisition (while the card is doing other tasks).之后,我使用map[offset]直接访问内存,其中 offset 以 4 字节为步长,而不是监督函数API::ReadRegister(offset)在某些情况下速度较慢并且严重延迟数据采集(而卡正在执行其他任务)。 The computer does not change the register contents, it just reads those.计算机不会更改寄存器内容,它只是读取这些内容。 The external independent card can change at any time the register content, which is why the keyword volatile was introducted in the example from the vendor, I believe.外部独立卡可以随时更改寄存器内容,这就是为什么在供应商的示例中引入关键字volatile的原因,我相信。

If this is for initialization, then I guess what it does is fill in a void * , not anything else, ie as if in C++ you'd have a parameter of type void *& .如果这是用于初始化,那么我猜它的作用是填充一个void * ,而不是其他任何东西,即就像在 C++ 中一样,您将有一个void *&类型的参数。

I believe it is intended to be used as我相信它旨在用作

void *ptr;
if (API::InitializeRegisterMap(&ptr)) {
    ...
}

then afterwards you will take the value in ptr and convert that value to volatile uint32_t *map :然后之后您将获取ptr的值并将值转换volatile uint32_t *map

void *ptr;
volatile std::uint32_t *map;
if (API::InitializeRegisterMap(&ptr)) {
    map = static_cast<std::uint32_t *>(ptr);
}

Most notably in C , as opposed to C++, this can be written completely castless , which should be considered a good sign.最值得注意的是,在C 中,与 C++ 不同,这可以完全不用 cast ,这应该被认为是一个好兆头。

Also, you want to avoid reinterpret_cast like the plague.此外,您想避免reinterpret_cast像瘟疫一样。

After several trial and error steps, I noticed that this cannot be done with a simple cast step, you need to concatenate two:经过几次反复试验后,我注意到这不能通过简单的转换步骤来完成,您需要连接两个:

void** argForSomeAPIfunction = reinterpret_cast<void**>(const_cast<uint32_t**>(&map));

The inner one is needed to cast away the volatile-ness, the second one for converting from int to void.需要内部一个来摆脱 volatile-ness,第二个用于从 int 转换为 void。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM