typedef 结构导致 "pointer to incomplete type not allowed" 错误
typedef struct leads to "pointer to incomplete type not allowed" error
我正在使用的库在其 header (http_client.h
) 中包含以下声明:
typedef struct _httpc_state httpc_state_t;
库在实现中定义了结构体 (http_client.c
)
typedef struct _httpc_state
{
struct altcp_pcb* pcb;
ip_addr_t remote_addr;
u16_t remote_port;
int timeout_ticks;
struct pbuf *request;
struct pbuf *rx_hdrs;
u16_t rx_http_version;
u16_t rx_status;
altcp_recv_fn recv_fn;
const httpc_connection_t *conn_settings;
void* callback_arg;
u32_t rx_content_len;
u32_t hdr_content_len;
httpc_parse_state_t parse_state;
#if HTTPC_DEBUG_REQUEST
char* server_name;
char* uri;
#endif
} httpc_state_t;
在同一个 C 文件中,它实现了以下使用结构的函数:
/** http client tcp poll callback */
static err_t
httpc_tcp_poll(void *arg, struct altcp_pcb *pcb)
{
/* implement timeout */
httpc_state_t* req = (httpc_state_t*)arg; // Here the void pointer is casted to httpc_state_t
LWIP_UNUSED_ARG(pcb);
if (req != NULL) {
if (req->timeout_ticks) { // Here the concrete type is used. Works. No problems.
req->timeout_ticks--;
}
if (!req->timeout_ticks) {
return httpc_close(req, HTTPC_RESULT_ERR_TIMEOUT, 0, ERR_OK);
}
}
return ERR_OK;
}
我有一个使用这个库的 C++ 文件,当然包括所需的 header (http_client.h
)。
extern "C"
{
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "lwip/tcpip.h"
#include "lwip/apps/http_client.h" // Here I include their http_client.h file
#include "projdefs.h"
}
在我的下一个函数中,我需要完全执行它们的实现。我需要用 httpc_state_t
做点什么。我实现了他们的回调函数如下:
err_t rec_fn(void *arg, struct altcp_pcb *conn, struct pbuf *p, err_t err)
{
if (p)
{
httpc_state_t* req = (httpc_state_t*)arg; // Compiler sees no problems in casting to my desired type....
req->timeout_ticks = 30; // COMPILE ERROR, pointer to incomplete class type _httpc_state is not allowed
}
}
为什么会出现编译错误?! Header 包含文件。 Header 文件声明了 typedef。即使在阅读 this and this 之后,我仍然看不出我做错了什么....
不完整的类型表示它已声明但未定义。您需要在头文件中定义该结构并将其包含到您的 C 文件中。
在定义函数 rec_fn
的翻译单元中,编译器只会看到以下声明
typedef struct _httpc_state httpc_state_t;
它不知道该语句中使用的数据成员timeout_ticks
是否
req->timeout_ticks = 30;
确实是在结构struct _httpc_state
中声明的,它的类型是什么。即名称 timeout_ticks
未在此翻译单元中声明。所以编译器报错。
如果您要在翻译单元中使用结构的数据成员,那么编译器需要知道它们的声明。也就是说,您还需要包括结构定义。
如果允许,请移动 header 中的结构定义,或者在定义函数的模块中复制其定义。
注意,如果结构定义没有放在 header 中,原因可能是代码的作者不想让它在他的模块或库之外可用。
错误消息措辞不当。
指向不完整类型的指针没问题!
取消对不完整类型成员的引用是个问题。
在错误发生的地方,编译器没有'seen'该翻译单元中类型的完整定义。
它识别类型,但不知道该类型是否有成员 timeout_ticks
更不用说如何生成访问它的代码了。
[例如成员相对于对象开头的位置。]
指向不完整类型的指针是减少依赖性和代码耦合的有用方法。如果代码只需要传递指向某个类型的指针,则可以声明该类型(不完整)并帮助进行类型检查,但不会暴露给完整的定义。
我正在使用的库在其 header (http_client.h
) 中包含以下声明:
typedef struct _httpc_state httpc_state_t;
库在实现中定义了结构体 (http_client.c
)
typedef struct _httpc_state
{
struct altcp_pcb* pcb;
ip_addr_t remote_addr;
u16_t remote_port;
int timeout_ticks;
struct pbuf *request;
struct pbuf *rx_hdrs;
u16_t rx_http_version;
u16_t rx_status;
altcp_recv_fn recv_fn;
const httpc_connection_t *conn_settings;
void* callback_arg;
u32_t rx_content_len;
u32_t hdr_content_len;
httpc_parse_state_t parse_state;
#if HTTPC_DEBUG_REQUEST
char* server_name;
char* uri;
#endif
} httpc_state_t;
在同一个 C 文件中,它实现了以下使用结构的函数:
/** http client tcp poll callback */
static err_t
httpc_tcp_poll(void *arg, struct altcp_pcb *pcb)
{
/* implement timeout */
httpc_state_t* req = (httpc_state_t*)arg; // Here the void pointer is casted to httpc_state_t
LWIP_UNUSED_ARG(pcb);
if (req != NULL) {
if (req->timeout_ticks) { // Here the concrete type is used. Works. No problems.
req->timeout_ticks--;
}
if (!req->timeout_ticks) {
return httpc_close(req, HTTPC_RESULT_ERR_TIMEOUT, 0, ERR_OK);
}
}
return ERR_OK;
}
我有一个使用这个库的 C++ 文件,当然包括所需的 header (http_client.h
)。
extern "C"
{
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "lwip/tcpip.h"
#include "lwip/apps/http_client.h" // Here I include their http_client.h file
#include "projdefs.h"
}
在我的下一个函数中,我需要完全执行它们的实现。我需要用 httpc_state_t
做点什么。我实现了他们的回调函数如下:
err_t rec_fn(void *arg, struct altcp_pcb *conn, struct pbuf *p, err_t err)
{
if (p)
{
httpc_state_t* req = (httpc_state_t*)arg; // Compiler sees no problems in casting to my desired type....
req->timeout_ticks = 30; // COMPILE ERROR, pointer to incomplete class type _httpc_state is not allowed
}
}
为什么会出现编译错误?! Header 包含文件。 Header 文件声明了 typedef。即使在阅读 this and this 之后,我仍然看不出我做错了什么....
不完整的类型表示它已声明但未定义。您需要在头文件中定义该结构并将其包含到您的 C 文件中。
在定义函数 rec_fn
的翻译单元中,编译器只会看到以下声明
typedef struct _httpc_state httpc_state_t;
它不知道该语句中使用的数据成员timeout_ticks
是否
req->timeout_ticks = 30;
确实是在结构struct _httpc_state
中声明的,它的类型是什么。即名称 timeout_ticks
未在此翻译单元中声明。所以编译器报错。
如果您要在翻译单元中使用结构的数据成员,那么编译器需要知道它们的声明。也就是说,您还需要包括结构定义。
如果允许,请移动 header 中的结构定义,或者在定义函数的模块中复制其定义。
注意,如果结构定义没有放在 header 中,原因可能是代码的作者不想让它在他的模块或库之外可用。
错误消息措辞不当。
指向不完整类型的指针没问题! 取消对不完整类型成员的引用是个问题。
在错误发生的地方,编译器没有'seen'该翻译单元中类型的完整定义。
它识别类型,但不知道该类型是否有成员 timeout_ticks
更不用说如何生成访问它的代码了。
[例如成员相对于对象开头的位置。]
指向不完整类型的指针是减少依赖性和代码耦合的有用方法。如果代码只需要传递指向某个类型的指针,则可以声明该类型(不完整)并帮助进行类型检查,但不会暴露给完整的定义。