Linux交叉编译Windows CGo代码时出现未知类型名错误
解决Linux交叉编译Windows CGO代码时DISPLAYCONFIG相关类型未定义问题
问题场景
在Linux环境下通过Docker交叉编译Windows平台的CGO程序,调用QueryDisplayConfig等Windows API时,出现以下编译错误:
winhelpers_windows.c: In function 'CQueryDisplayConfig': winhelpers_windows.c:11:5: error: unknown type name 'DISPLAYCONFIG_PATH_INFO' winhelpers_windows.c:13:5: error: unknown type name 'DISPLAYCONFIG_MODE_INFO' winhelpers_windows.c:14:5: error: unknown type name 'DISPLAYCONFIG_TOPOLOGY_ID' winhelpers_windows.c:16:24: warning: implicit declaration of function 'QueryDisplayConfig'
已确认/usr/x86_64-w64-mingw32/include目录下的wingdi.h和winuser.h中存在这些类型和函数的定义,且代码中已包含windows.h。
原因分析
DISPLAYCONFIG_*类型和QueryDisplayConfig函数属于Windows Vista及以上版本的API,mingw-w64的头文件中这些定义被条件编译包裹,默认未启用。必须定义特定宏才能让编译器识别这些声明:
- 需要定义
_WIN32_WINNT >= 0x0600(对应Windows Vista版本) - 或定义
WINVER >= 0x0600
解决方案
方式1:在编译命令中添加宏定义
修改CGO_CFLAGS,增加宏定义参数,同时修正LDFLAGS中的错误写法:
export PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig; GOOS=windows GOARCH=amd64 CGO_ENABLED=1 \ CGO_CFLAGS="-isystem /usr/x86_64-w64-mingw32/include -I/usr/x86_64-w64-mingw32/lib/pkgconfig -I/usr/x86_64-w64-mingw32/include \ -I /usr/x86_64-w64-mingw32/include/gst-include/glib-2.0 \ -I/usr/share/mingw-w64/include -I/usr/x86_64-w64-mingw32/include/gst-include/gstreamer-1.0 \ -D_WIN32_WINNT=0x0600" \ CGO_LDFLAGS="-L/usr/x86_64-w64-mingw32/lib -luser32" \ CXX=x86_64-w64-mingw32-g++ \ CC=x86_64-w64-mingw32-gcc go build -o bin/yaoe.exe main.go
注:原LDFLAGS中的
-Luser32是错误写法,链接库需用小写-l,路径用-L指定。
方式2:在C头文件中提前定义宏
修改windows_helpers.h,在包含windows.h之前添加宏定义:
#ifndef WINHELPERS_H #define WINHELPERS_H #define _WIN32_WINNT 0x0600 #define WINVER 0x0600 #include <windows.h> LPCSTR wrapMAKEINTRESOURCEA(UINT_PTR i); void CQueryDisplayConfig(); #endif // WINHELPERS_H
额外修正Go文件中的编译参数
检查Go文件中的#cgo指令,修正LDFLAGS的错误写法:
/* #cgo CFLAGS: -I . -I/usr/x86_64-w64-mingw32/include -D_WIN32_WINNT=0x0600 #cgo LDFLAGS: -L/usr/x86_64-w64-mingw32/lib -luser32 #include "winhelpers_windows.h" */ import "C"
验证方法
若仍有疑问,可查看mingw头文件的条件编译逻辑确认:
grep -B5 -A10 DISPLAYCONFIG_PATH_INFO /usr/x86_64-w64-mingw32/include/wingdi.h
会看到类似#if (_WIN32_WINNT >= 0x0600)的条件语句,确认宏定义是否生效。
内容的提问来源于stack exchange,提问作者Riptide
相关产品推荐
相关产品推荐

