为什么 cgo 生成“C”警告消息,但纯“C”等价物却不会?

问题描述 投票:0回答:1

为什么我使用 cgo 编译以下在 Windows 上使用 Mediainfo.dll 的非常简单的应用程序:

package main

// #cgo CFLAGS: -DUNICODE
// #cgo CFLAGS: -I./MediaInfoDLL
// #cgo LDFLAGS: -L./MediaInfoDLL -lMediaInfo
// #include "MediaInfoDLL.h"
import "C"

func main() {
    C.MediaInfoDLL_Load()
}

它会生成以下有关 MediaInfoDLL.h 文件问题的警告:

In file included from .\test.go:6:
.\mediainfo\MediaInfoDLL/MediaInfoDLL.h: In function 'MediaInfoDLL_Load':
.\mediainfo\MediaInfoDLL/MediaInfoDLL.h:127:39: warning: passing argument 1 of 'LoadLibraryW' from incompatible pointer type [-Wincompatible-pointer-types]      
  127 |             #define MEDIAINFODLL_NAME "MediaInfo.dll"
      |                                       ^~~~~~~~~~~~~~~
      |                                       |
      |                                       char *
.\mediainfo\MediaInfoDLL/MediaInfoDLL.h:350:40: note: in expansion of macro 'MEDIAINFODLL_NAME'
  350 |         MediaInfo_Module = LoadLibrary(MEDIAINFODLL_NAME);
      |                                        ^~~~~~~~~~~~~~~~~
In file included from C:/TDM-GCC-64/x86_64-w64-mingw32/include/winbase.h:24,
                 from C:/TDM-GCC-64/x86_64-w64-mingw32/include/windows.h:70,
                 from .\mediainfo\MediaInfoDLL/MediaInfoDLL.h:243,
                 from .\test.go:6:
C:/TDM-GCC-64/x86_64-w64-mingw32/include/libloaderapi.h:142:48: note: expected 'LPCWSTR' {aka 'const short unsigned int *'} but argument is of type 'char *'     
  142 | WINBASEAPI HMODULE WINAPI LoadLibraryW(LPCWSTR lpLibFileName);
      |                                        ~~~~~~~~^~~~~~~~~~~~~
In file included from .\test.go:6:
At top level:
.\mediainfo\MediaInfoDLL/MediaInfoDLL.h:449:17: warning: 'MediaInfoDLL_UnLoad' defined but not used [-Wunused-function]
  449 |     static void MediaInfoDLL_UnLoad()
      |                 ^~~~~~~~~~~~~~~~~~~
.\mediainfo\MediaInfoDLL/MediaInfoDLL.h:441:19: warning: 'MediaInfoDLL_IsLoaded' defined but not used [-Wunused-function]
  441 |     static size_t MediaInfoDLL_IsLoaded()
      |                   ^~~~~~~~~~~~~~~~~~~~~
.\mediainfo\MediaInfoDLL/MediaInfoDLL.h:333:38: warning: 'MediaInfo_Count_Get_Files' defined but not used [-Wunused-variable]
  333 |     static MEDIAINFO_Count_Get_Files MediaInfo_Count_Get_Files;
      |                                      ^~~~~~~~~~~~~~~~~~~~~~~~~

如果我编译与纯“C”完全相同的“C”代码,我不会收到任何警告消息:

#include "MediaInfoDLL.h"

int main()
{
    MediaInfoDLL_Load();
}

为什么 cgo 会生成警告(我认为应该生成),但编译相同的代码作为 .c 文件不会产生警告消息?

c go cgo
1个回答
2
投票

这是由于

MediaInfoDLL.h

的问题造成的

说明

// #cgo CFLAGS: -DUNICODE

定义 C 预处理器符号

UNICODE
。 WIN32 标头旨在构建具有宽字符的应用程序 (
wchar_t
)。定义
UNICODE
后,API 名称将以
W
结尾扩展:
LoadLibrary
->
LoadLibraryW

LoadLibraryW
要求参数的类型为
LPWCHAR
,即
wchar_t*
。但警告表明实际参数的类型为
char*

该问题是由于

MediaInfoDLL.h
中的错误引起的:

    #ifdef _UNICODE
        #ifndef MEDIAINFODLL_NAME
            #define MEDIAINFODLL_NAME L"MediaInfo.dll"
        #endif //MEDIAINFODLL_NAME
    #else //_UNICODE
        #ifndef MEDIAINFODLL_NAME
            #define MEDIAINFODLL_NAME "MediaInfo.dll"
        #endif //MEDIAINFODLL_NAME
    #endif //_UNICODE

他们不会检查您为

UNICODE
定义的
cgo
符号。

有两种修复方法:

  1. -DUNICODE
    中删除
    CFLAGS
    。二进制将是 ASCII。
  2. -D_UNICODE
    添加到
    CFLAGS
    // #cgo CFLAGS: -DUNICODE -D_UNICODE
    - 构建 Unicode 二进制文件。

两种解决方案都可以编译并运行。

© www.soinside.com 2019 - 2024. All rights reserved.