为什么在 Windows 上使用 dirent.h 时会出现不完整的类型错误?
Why am I getting an incomplete type error when using dirent.h on Windows?
我有一个结合了多个 .c 和 .h 文件的 C 项目。以前我只是将所有这些文件以及以下 Makefile 放在顶级目录中:
O = o
E =
CC = gcc
OUT = cusum$E
CFLAGS = -D_GNU_SOURCE -O3 -Wall -Wextra --static
DEPS = bessel.h detector.h io.h stepfit.h lmmin_int64.h utils.h
ODIR = obj
_OBJ = main.$O bessel.$O detector.$O io.$O lmmin_int64.$O stepfit.$O utils.$O
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
LIBS = -lm
$(ODIR)/%.$O: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS) $(LIBS)
$(OUT): $(OBJ)
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
.PHONY: clean win
clean:
rm -f $(OUT) $(ODIR)/*.$O *~ core $(INCDIR)/*~
rm -f $(OUT).exe w$(ODIR)/*.obj *~ core $(INCDIR)/*~
win:
$(MAKE) CC=x86_64-w64-mingw32-gcc E=.exe O=obj ODIR=wobj
据我所知,这工作正常。
然后我重新组织了一些东西,将 .c
文件放在 src
文件夹中,将 .h
文件放在 lib
文件夹中。我将 Makefile 更改为以下内容:
O = o
E =
CC = gcc
OUT = dist/cusum$E
CFLAGS = -D_GNU_SOURCE -O3 -Wall -Wextra --static
INCDIR = lib/
DEPS = lib/*.h
ODIR = build/obj
_OBJ = main.$O bessel.$O detector.$O io.$O lmmin_int64.$O stepfit.$O utils.$O
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
LIBS = -lm
$(ODIR)/%.$O: src/%.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS) -I$(INCDIR) $(LIBS)
$(OUT): $(OBJ)
$(CC) -o $@ $^ $(CFLAGS) -I$(INCDIR) $(LIBS)
.PHONY: clean win cleanwin
clean:
rm -f $(OUT) $(ODIR)/*.$(O) *~ core $(INCDIR)/*~
win:
$(MAKE) CC=x86_64-w64-mingw32-gcc E=.exe O=obj ODIR=build/wobj
cleanwin:
$(MAKE) clean CC=x86_64-w64-mingw32-gcc E=.exe O=obj ODIR=build/wobj
现在,当我为 Linux (make
) 编译时,它工作正常。当我为 windows (make win
) 交叉编译时,出现以下错误:
`make[1]: Entering directory '[...]'
x86_64-w64-mingw32-gcc -c -o build/wobj/main.obj src/main.c -D_GNU_SOURCE -O3 -Wall -Wextra --static -Ilib/ -lm
In file included from lib/io.h:31:0,
from src/main.c:21:
/usr/share/mingw-w64/include/dirent.h:41:21: error: field ‘dd_dta’ has incomplete type
struct _finddata_t dd_dta;
^~~~~~
/usr/share/mingw-w64/include/dirent.h:88:22: error: field ‘dd_dta’ has incomplete type
struct _wfinddata_t dd_dta;
`
main.c
通过以下方式包含所有库:
#include"lib1.h"
#include"lib2.h"
....
并且位于 src
文件夹中
如果我 return 将文件夹结构恢复到原来的样子并使用旧的 Makefile,它可以正常工作并测试,所以我认为问题出在 Makefile 而不是代码本身。谁能指出我正确的方向?如果缺少任何信息,请告诉我,以便我进行修复。
所以 windows 版本的 MinGW 似乎有一些定义问题。添加到我的 include/dirent.h
编译器版本中的以下代码为我解决了这个问题。编辑库函数一般来说可能不是一个好主意,所以只有当你喜欢冒险时才使用它......我没有声称这不会破坏其他地方的所有东西。
#ifndef _FSIZE_T_DEFINED
typedef unsigned long _fsize_t;
#define _FSIZE_T_DEFINED
#endif
struct _finddata_t
{
unsigned attrib; /* Attributes, see constants above. */
time_t time_create;
time_t time_access; /* always midnight local time */
time_t time_write;
_fsize_t size;
char name[FILENAME_MAX]; /* may include spaces. */
};
struct _wfinddata_t
{
unsigned attrib; /* Attributes, see constants above. */
time_t time_create;
time_t time_access; /* always midnight local time */
time_t time_write;
size_t size;
wchar_t name[FILENAME_MAX]; /* may include spaces. */
};
文件 io.h 中的原因。当您将 io.h 移动到子目录时,dirent.h 想要包含您的文件而不是系统文件。
#include <io.h>
要解决这种情况,只需重命名您的 io.h。
我有一个结合了多个 .c 和 .h 文件的 C 项目。以前我只是将所有这些文件以及以下 Makefile 放在顶级目录中:
O = o
E =
CC = gcc
OUT = cusum$E
CFLAGS = -D_GNU_SOURCE -O3 -Wall -Wextra --static
DEPS = bessel.h detector.h io.h stepfit.h lmmin_int64.h utils.h
ODIR = obj
_OBJ = main.$O bessel.$O detector.$O io.$O lmmin_int64.$O stepfit.$O utils.$O
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
LIBS = -lm
$(ODIR)/%.$O: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS) $(LIBS)
$(OUT): $(OBJ)
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
.PHONY: clean win
clean:
rm -f $(OUT) $(ODIR)/*.$O *~ core $(INCDIR)/*~
rm -f $(OUT).exe w$(ODIR)/*.obj *~ core $(INCDIR)/*~
win:
$(MAKE) CC=x86_64-w64-mingw32-gcc E=.exe O=obj ODIR=wobj
据我所知,这工作正常。
然后我重新组织了一些东西,将 .c
文件放在 src
文件夹中,将 .h
文件放在 lib
文件夹中。我将 Makefile 更改为以下内容:
O = o
E =
CC = gcc
OUT = dist/cusum$E
CFLAGS = -D_GNU_SOURCE -O3 -Wall -Wextra --static
INCDIR = lib/
DEPS = lib/*.h
ODIR = build/obj
_OBJ = main.$O bessel.$O detector.$O io.$O lmmin_int64.$O stepfit.$O utils.$O
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
LIBS = -lm
$(ODIR)/%.$O: src/%.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS) -I$(INCDIR) $(LIBS)
$(OUT): $(OBJ)
$(CC) -o $@ $^ $(CFLAGS) -I$(INCDIR) $(LIBS)
.PHONY: clean win cleanwin
clean:
rm -f $(OUT) $(ODIR)/*.$(O) *~ core $(INCDIR)/*~
win:
$(MAKE) CC=x86_64-w64-mingw32-gcc E=.exe O=obj ODIR=build/wobj
cleanwin:
$(MAKE) clean CC=x86_64-w64-mingw32-gcc E=.exe O=obj ODIR=build/wobj
现在,当我为 Linux (make
) 编译时,它工作正常。当我为 windows (make win
) 交叉编译时,出现以下错误:
`make[1]: Entering directory '[...]'
x86_64-w64-mingw32-gcc -c -o build/wobj/main.obj src/main.c -D_GNU_SOURCE -O3 -Wall -Wextra --static -Ilib/ -lm
In file included from lib/io.h:31:0,
from src/main.c:21:
/usr/share/mingw-w64/include/dirent.h:41:21: error: field ‘dd_dta’ has incomplete type
struct _finddata_t dd_dta;
^~~~~~
/usr/share/mingw-w64/include/dirent.h:88:22: error: field ‘dd_dta’ has incomplete type
struct _wfinddata_t dd_dta;
`
main.c
通过以下方式包含所有库:
#include"lib1.h"
#include"lib2.h"
....
并且位于 src
文件夹中
如果我 return 将文件夹结构恢复到原来的样子并使用旧的 Makefile,它可以正常工作并测试,所以我认为问题出在 Makefile 而不是代码本身。谁能指出我正确的方向?如果缺少任何信息,请告诉我,以便我进行修复。
所以 windows 版本的 MinGW 似乎有一些定义问题。添加到我的 include/dirent.h
编译器版本中的以下代码为我解决了这个问题。编辑库函数一般来说可能不是一个好主意,所以只有当你喜欢冒险时才使用它......我没有声称这不会破坏其他地方的所有东西。
#ifndef _FSIZE_T_DEFINED
typedef unsigned long _fsize_t;
#define _FSIZE_T_DEFINED
#endif
struct _finddata_t
{
unsigned attrib; /* Attributes, see constants above. */
time_t time_create;
time_t time_access; /* always midnight local time */
time_t time_write;
_fsize_t size;
char name[FILENAME_MAX]; /* may include spaces. */
};
struct _wfinddata_t
{
unsigned attrib; /* Attributes, see constants above. */
time_t time_create;
time_t time_access; /* always midnight local time */
time_t time_write;
size_t size;
wchar_t name[FILENAME_MAX]; /* may include spaces. */
};
文件 io.h 中的原因。当您将 io.h 移动到子目录时,dirent.h 想要包含您的文件而不是系统文件。
#include <io.h>
要解决这种情况,只需重命名您的 io.h。