Echoxxzz
Echoxxzz

Reputation: 11

Why does cgo generate "C" warning messages but the pure "C" equivalent doesn't?

Why I compile the following very simple app that is using the Mediainfo.dll on Windows using cgo:

package main

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

func main() {
    C.MediaInfoDLL_Load()
}

it generates the following warnings about problems with the MediaInfoDLL.h file:

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;
      |                                      ^~~~~~~~~~~~~~~~~~~~~~~~~

If I compile the exact same "C" code as pure "C" I don't get any warning messages:

#include "MediaInfoDLL.h"

int main()
{
    MediaInfoDLL_Load();
}

Why does cgo generate warning (which I think should be generated) but compiling the same code as a .c file produces no warning messages?

Upvotes: 1

Views: 70

Answers (1)

Pak Uula
Pak Uula

Reputation: 3435

This is due to an issue with MediaInfoDLL.h

The instruction

// #cgo CFLAGS: -DUNICODE

defines C preprocessor symbol UNICODE. The WIN32 headers are designed to build applications with wide chars (wchar_t). When UNICODE is defined, API names are expanded with W ending: LoadLibrary -> LoadLibraryW

LoadLibraryW requires the argument to be of type LPWCHAR, that is wchar_t*. But the warning tells that the actual argument is of type char*.

The issue is due to the bug in 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

They don't check UNICODE symbol that you defined for cgo.

There are two ways to fix:

  1. Remove -DUNICODE from CFLAGS. The binary will be ASCII.
  2. Add -D_UNICODE to CFLAGS: // #cgo CFLAGS: -DUNICODE -D_UNICODE - to build a Unicode binary.

Both solutions compile and run.

Upvotes: 2

Related Questions