代码之家  ›  专栏  ›  技术社区  ›  MrZigha

如何在C for Windows中正确链接到库[重复]

  •  0
  • MrZigha  · 技术社区  · 2 年前

    我目前正在尝试为Windows编写C程序。我有Windows 11,我在VS code上编码,我已经安装了MinGW并正确地将其添加到PATH中。问题是我无法将我的程序链接到 libiphlapi ws2_32 图书馆。

    这是我的工作环境:

    tree /F
    D:.
    │   Makefile
    │
    ├───.vscode
    │       settings.json
    │
    ├───build
    ├───include
    │       windows_backup_scheduler.h
    │
    ├───obj
    │       hwid.o
    │       main.o
    │
    └───src
            hwid.c
            main.c
    

    生成文件:

    BUILD_DIR := build
    INCLUDE_DIR := include
    OBJ_DIR := obj
    SRC_DIR := src
    NAME := windows_backup_scheduler.exe
    
    CC := gcc
    CFLAGS := -m64 -fPIE -Wall -Wextra -Werror -pedantic -g3
    LFLAGS := -I$(INCLUDE_DIR) -I"C:\MinGW\include" -L"C:\MinGW\x86_64-w64-mingw32\lib" -liphlpapi -lws2_32 -static-libgcc
    
    SRC_FILES := $(wildcard $(SRC_DIR)/*.c)
    OBJ_FILES := $(patsubst $(SRC_DIR)/%.c, $(OBJ_DIR)/%.o, $(SRC_FILES))
    TARGET := $(BUILD_DIR)/$(NAME)
    
    all: $(TARGET)
    
    $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
        $(CC) $(CFLAGS) $(LFLAGS) -c $< -o $@
    
    $(TARGET): $(OBJ_FILES)
        $(CC) $(CFLAGS) $(LFLAGS) -o $@ $^
    
    clean:
        @del /Q $(OBJ_DIR)\*.o
    
    fclean: clean
        @del /Q $(BUILD_DIR)\$(NAME)
    
    re: fclean all
    

    windows_backup_scheduler。h

    #ifndef WINDOWS_BACKUP_SCHEDULER_H
        #define WINDOWS_BACKUP_SCHEDULER_H
    
        #ifndef NULL
            #define NULL (void *)0;
        #endif
    
        #include <stdio.h>
        #include <tchar.h>
        #include <winsock2.h>
        #include <iphlpapi.h>
        #include <windows.h>
    
        char *GetMACAddress(void);
    
    #endif
    

    主要的c

    #include <windows_backup_scheduler.h>
    
    int main(void)
    {
        printf("MAC %s\n", GetMACAddress());
        return (0);
    }
    

    hwid。c

    #include <windows_backup_scheduler.h>
    
    char *GetMACAddress(void)
    {
        IP_ADAPTER_INFO* AdapterInfo = NULL;
        ULONG ulBufLen = 0;
        DWORD dwStatus = 0;
        char* macAddr = NULL;
    
        if (GetAdaptersInfo(AdapterInfo, &ulBufLen) == ERROR_BUFFER_OVERFLOW) {
            if ((AdapterInfo = malloc(ulBufLen)) == NULL) {
                return (NULL);
            }
        }
        if ((dwStatus = GetAdaptersInfo(AdapterInfo, &ulBufLen)) != ERROR_SUCCESS) {
            free(AdapterInfo);
            return (NULL);
        }
        if ((macAddr = (char*)malloc(18)) == NULL) {
            free(AdapterInfo);
            return (NULL);
        }
        snprintf(macAddr, 18, "%02X-%02X-%02X-%02X-%02X-%02X",
                AdapterInfo[0].Address[0], AdapterInfo[0].Address[1],
                AdapterInfo[0].Address[2], AdapterInfo[0].Address[3],
                AdapterInfo[0].Address[4], AdapterInfo[0].Address[5]);
        free(AdapterInfo);
        return (macAddr);
    }
    

    当我尝试编译时,我会得到以下信息:

    D:\WMP\Training\Windows_Backup_Scheduler>make re
    Unable to find D:\WMP\Training\Windows_Backup_Scheduler\build\windows_backup_scheduler.exe
    gcc -m64 -fPIE -Wall -Wextra -Werror -pedantic -g3 -Iinclude -I"C:\MinGW\include" -L"C:\MinGW\x86_64-w64-mingw32\lib" -liphlpapi -lws2_32 -static-libgcc -c src/hwid.c -o obj/hwid.o
    gcc -m64 -fPIE -Wall -Wextra -Werror -pedantic -g3 -Iinclude -I"C:\MinGW\include" -L"C:\MinGW\x86_64-w64-mingw32\lib" -liphlpapi -lws2_32 -static-libgcc -c src/main.c -o obj/main.o
    gcc -m64 -fPIE -Wall -Wextra -Werror -pedantic -g3 -Iinclude -I"C:\MinGW\include" -L"C:\MinGW\x86_64-w64-mingw32\lib" -liphlpapi -lws2_32 -static-libgcc -o build/windows_backup_scheduler.exe obj/hwid.o obj/main.o
    c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: obj/hwid.o: in function `GetMACAddress':
    D:\WMP\Training\Windows_Backup_Scheduler/src/hwid.c:10: undefined reference to `GetAdaptersInfo'
    c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: D:\WMP\Training\Windows_Backup_Scheduler/src/hwid.c:15: undefined reference to `GetAdaptersInfo'
    collect2.exe: error: ld returned 1 exit status
    make: *** [Makefile:21: build/windows_backup_scheduler.exe] Error 1
    

    VSCode找到了头文件,并且 libiphlapi.a ws2_32.a C:\MinGW\x86_64-w64-mingw32\lib 和中的标头 C:\MinGW\include

    你能给我一个解决方案吗?

    1 回复  |  直到 2 年前
        1
  •  1
  •   MadScientist    2 年前

    您的变量没有正确分离。

    你需要为 编译器 的一组变量和标志中 连接器 在一组不同的变量中。例如:

    LFLAGS := -I$(INCLUDE_DIR) -I"C:\MinGW\include" -L"C:\MinGW\x86_64-w64-mingw32\lib" -liphlpapi -lws2_32 -static-libgcc
    

    这是错误的,因为 -I 编译器 选项,同时 -L -l 连接器 选项。您不应该将它们放在同一个变量中,因为您不需要将编译器标志传递给链接器,也绝对不希望将链接器标志传递给编译器。

    但是,您看到的链接错误的主要直接问题是,您必须将库( -l.... ) 之后 链接行中的对象文件。大多数链接器都是“单程”链接器,这意味着它们只链接在命令行上处理库时需要的符号,而链接器在处理对象文件之前不会知道库需要什么符号。

    如果你想使用标准的make变量(当然,如果你不想的话,你不必这么做),你应该使用:

    CC := gcc
    CFLAGS := -m64 -fPIE -Wall -Wextra -Werror -pedantic -g3
    CPPFLAGS := -I$(INCLUDE_DIR) -I"C:\MinGW\include"
    LDFLAGS := -L"C:\MinGW\x86_64-w64-mingw32\lib"
    LDLIBS := -liphlpapi -lws2_32 -static-libgcc
    

    然后你会写:

    $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
            $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
    
    $(TARGET): $(OBJ_FILES)
            $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
    
    推荐文章