CGO遇到的问题解决

CGO调用海康威视SDK #

问题一:宏定义问题 #

在C语言中,extern "C" 是用于指定C++编译器按照C语言的方式进行函数名的命名规则和链接的修饰符。然而,根据您提供的错误信息,您正在使用的是C语言的编译器(gcc),而不是C++编译器。

cgo: 
gcc errors for preamble:
In file included from .\hikvision.go:6:0:

error: expected identifier or '(' before string constant
     #define NET_DVR_API  extern "C" __declspec(dllimport)
     
note: in definition of macro 'NET_DVR_API'
     #define NET_DVR_API  extern "C" __declspec(dllimport)
                                 ^~~

添加这个:

#ifndef __cplusplus
    #define NET_DVR_API
#else
    #define NET_DVR_API extern "C"
#endif

原文件

#ifndef _HC_NET_SDK_H_
#define _HC_NET_SDK_H_

#ifndef _WINDOWS_
    #if (defined(_WIN32) || defined(_WIN64))
        #include <winsock2.h>
        #include <windows.h>    
    #endif
#endif

#if defined(_WIN64)
    #define OS_WINDOWS64    1
#endif

#if defined(__LP64__)
    #define OS_POSIX64    1 
#endif

#ifndef __PLAYRECT_defined
    #define __PLAYRECT_defined
    typedef struct __PLAYRECT
    {
        int x;                               
        int y;                                  
        int uWidth;                            
        int uHeight;                            
    }PLAYRECT;
#endif

#if (defined(_WIN32)) //windows
    //#define NET_DVR_API  extern "C" __declspec(dllimport)  防止宏被重复定义 这里注释掉
    typedef  unsigned __int64   UINT64;
    typedef  signed   __int64   INT64;
#elif defined(__linux__) || defined(__APPLE__) //linux
    #define  BOOL  int
    typedef  unsigned int       DWORD;
    typedef  unsigned short     WORD;
    typedef  unsigned short     USHORT;
    typedef  short              SHORT;
    typedef  int                LONG;
    typedef  unsigned char      BYTE;
    typedef  unsigned int       UINT;
    typedef  void*              LPVOID;
    typedef  void*              HANDLE;
    typedef  unsigned int*      LPDWORD; 
    typedef  unsigned long long UINT64;
    typedef  signed long long   INT64;

    #ifndef TRUE
        #define TRUE  1
    #endif
    #ifndef FALSE
        #define FALSE 0
    #endif
    #ifndef NULL
        #define NULL 0
    #endif

    #define __stdcall 
    #define CALLBACK  

    #define NET_DVR_API extern "C"
    typedef unsigned int   COLORKEY;
    typedef unsigned int   COLORREF;

    #ifndef __HWND_defined
        #define __HWND_defined
        #if defined(__APPLE__) || defined(ANDROID)
            typedef void* HWND;
        #elif defined(__linux__)
            typedef unsigned int HWND;
        #else
            typedef void* HWND;
        #endif
    #endif

    #ifndef __HDC_defined
        #define __HDC_defined
        #if defined(__linux__)
            typedef struct __DC
            {
                void*   surface;        //SDL Surface
                HWND    hWnd;           //HDC window handle
            }DC;
            typedef DC* HDC;
        #else
            typedef void* HDC;
        #endif
    #endif

    typedef struct tagInitInfo
    {
        int uWidth; 
        int uHeight; 
    }INITINFO; 
#endif

#ifndef __cplusplus
    #define NET_DVR_API
#else
    #define NET_DVR_API extern "C"
#endif

问题二:C语言不支持在函数参数列表中使用默认参数 #

cgo: 
gcc errors for preamble:
In file included from .\hikvision.go:6:0:
C:/Users/c/go/src/VideoForensic/GoldenEyes/videogoplugin/networkscan/include/HCNetSDK.h:51623:68: error: expected ';', ',' or ')' before '=' token
 NET_DVR_API BOOL __stdcall NET_DVR_SetConnectTime(DWORD dwWaitTime = 3000, DWORD dwTryTimes = 3);
                                                                    ^
C:/Users/c/go/src/VideoForensic/GoldenEyes/videogoplugin/networkscan/include/HCNetSDK.h:51624:66: error: expected ';', ',' or ')' before '=' token
 NET_DVR_API BOOL __stdcall NET_DVR_SetReconnect(DWORD dwInterval = 30000, BOOL bEnableRecon = TRUE);

修改方式:

NET_DVR_API BOOL __stdcall NET_DVR_SetReconnect(DWORD dwInterval = 30000, BOOL bEnableRecon = TRUE);
改成这样
NET_DVR_API BOOL __stdcall NET_DVR_SetReconnect(DWORD dwInterval, BOOL bEnableRecon);

问题三:使用了一个未知的类型名 ADDITIONAL_LIB #

 error: unknown type name 'ADDITIONAL_LIB'; did you mean 'PARTITION_LDM'?
 NET_DVR_API BOOL __stdcall NET_DVR_LoadAdditionalLib(ADDITIONAL_LIB libType, char const *sDllName);
                                                      ^~~~~~~~~~~~~~
                                                      PARTITION_LDM

CGO不认下面这个

enum ADDITIONAL_LIB 
{
    PLAYCTRL = 0,  
    DSSDK,        
    STREAMCONVERT,  
    STREAMTRANS,   
    QOSSDK,     
    DLL_PATH_AUDIO,  
    EZVIZ_SSL_SDK, 
    ANALYZE_DATA_LIB,
    DLL_LIBICONV,   
    SSLEAY32_SDK, 
    LIBEAY32_SDK,
    HCNETUTILS_SDK, 
    NPQ_LIB,  
    LOAD_DLL_COUNT,  
};

改成这样

typedef enum
{
    PLAYCTRL = 0,
    DSSDK,
    STREAMCONVERT,
    STREAMTRANS,
    QOSSDK,
    DLL_PATH_AUDIO,
    EZVIZ_SSL_SDK,
    ANALYZE_DATA_LIB,
    DLL_LIBICONV,
    SSLEAY32_SDK,
    LIBEAY32_SDK,
    HCNETUTILS_SDK,
    NPQ_LIB,
    LOAD_DLL_COUNT,
} ADDITIONAL_LIB;

CGO调用大华SDK #

问题一:宏定义问题 #

修改如下:

#ifndef DHNETSDK_H
#define DHNETSDK_H

#if (defined(_MSC_VER))
    #include <windows.h>
    #ifdef NETSDK_EXPORTS
		#if(defined(_WIN64) || defined(WIN64))
			#define CLIENT_NET_API
		#else
			#define CLIENT_NET_API      __declspec(dllexport) 
		#endif
    #else
        #define CLIENT_NET_API  __declspec(dllimport)
    #endif

    #define CALLBACK        __stdcall
    #define CALL_METHOD     __stdcall  ///__cdecl

    #define INT64           __int64
    #define TP_U64          unsigned __int64

    #ifndef LLONG
        #ifdef _WIN64
            #define LLONG   INT64
        #else 
            #define LLONG   LONG
        #endif
    #endif

    #ifndef LDWORD
        #ifdef _WIN64
            #define LDWORD  INT64
        #else 
            #define LDWORD  DWORD
        #endif
    #endif
#else    ///non-windows
    #define CLIENT_NET_API
    #define CALL_METHOD 
    #define CALLBACK

    #ifndef INTERNAL_COMPILE
        #define RELEASE_HEADER
    #endif
 
    #ifdef RELEASE_HEADER
        #define WORD        unsigned short
        #define DWORD       unsigned int
        #define LONG        int
        #define LPDWORD     DWORD*

        #ifdef __OBJC__
            #include "objc/objc.h"
        #else
            #define BOOL    int
        #endif

        #ifndef TRUE
        #define TRUE        1
        #endif

        #ifndef FALSE
        #define FALSE       0
        #endif
        #define BYTE        unsigned char
        #define UINT        unsigned int
        #define HDC         void*
        #define HWND        void*
        #define LPVOID      void*

        #ifndef NULL
        #define NULL        0
        #endif

        #define LLONG       long
        #define INT64       long long
        #define TP_U64      unsigned long long
        #define LDWORD      long 

        #ifndef MAX_PATH
        #define MAX_PATH    260
        #endif

        #ifndef DEF_RECT
		///@brief rect
        typedef struct  tagRECT
        {
            LONG left;
            LONG top;
            LONG right;
            LONG bottom;
        } RECT;
        #define DEF_RECT
        #endif
    #else    ///�ڲ�����
        #include "../../SRC/Platform/osIndependent.h"
        #define INT64       int64
        #define TP_U64      uint64
    #endif /// RELEASE_HEADER
#endif /// linux

#ifndef LDWORD
    #if (defined(WIN32) || defined(_WIN32) || defined(_WIN64))
        #ifdef _WIN64
            #define LDWORD  __int64
        #else ///WIN32 
            #define LDWORD  DWORD
        #endif
    #else    ///linux
        #define LDWORD      long 
    #endif
#endif


#ifdef __cplusplus
#define CLIENT_NET_API extern "C" {    //改的这里
#endif

问题二:C语言不支持在函数参数列表中使用默认参数 #

C:/Users/。/go/src/VideoForensic/GoldenEyes/videogoplugin/networkscan/include/dhnetsdk.h:131832:160: error: expected ';', ',' or ')' before '=' token
 CLIENT_NET_API BOOL CALL_METHOD CLIENT_DelMobilePushNotify(LLONG lLoginID, const NET_MOBILE_PUSH_NOTIFY_DEL *pstuIn, NET_OUT_DELETECFG* pstuOut, int nWaitTime = 1000);
                                                                                                                                                                ^
C:/Users/。/go/src/VideoForensic/GoldenEyes/videogoplugin/networkscan/include/dhnetsdk.h:131836:143: error: expected ';', ',' or ')' before '=' token
 CLIENT_NET_API BOOL CALL_METHOD CLIENT_GetMobilePushNotifyCfg(LLONG lLoginID, NET_MOBILE_PUSH_NOTIFY_CFG *pstuCfg, int *nError, int nWaitTime = 1000);
                                                                                                                                               ^
C:/Users/。/go/src/VideoForensic/GoldenEyes/videogoplugin/networkscan/include/dhnetsdk.h:131840:164: error: expected ';', ',' or ')' before '=' token
 CLIENT_NET_API BOOL CALL_METHOD CLIENT_SetMobilePushNotifyCfg(LLONG lLoginID, const NET_MOBILE_PUSH_NOTIFY_CFG *pstuCfg, int *nError, int *nRestart, int nWaitTime = 1000);
                                                                                                                                                                    ^
C:/Users/。/go/src/VideoForensic/GoldenEyes/videogoplugin/networkscan/include/dhnetsdk.h:131844:167: error: expected ';', ',' or ')' before '=' token
 CLIENT_NET_API BOOL CALL_METHOD CLIENT_DelMobilePushNotifyCfg(LLONG lLoginID, const NET_MOBILE_PUSH_NOTIFY_CFG_DEL *pstuIn, NET_OUT_DELETECFG* pstuOut, int nWaitTime = 1000);
除了删除没办法 跟上面一样

问题三:未定义类型 #

C:/Users/c/go/src/VideoForensic/GoldenEyes/videogoplugin/networkscan/include/dhnetsdk.h:6288:5: error: unknown type name 'bool'
#ifndef DHNETSDK_H
#define DHNETSDK_H

#if (defined(WIN32) || defined(_WIN32) || defined(_WIN64))
    #include <windows.h>
    #ifdef NETSDK_EXPORTS
		#if(defined(_WIN64) || defined(WIN64))
			#define CLIENT_NET_API
		#else
			#define CLIENT_NET_API      __declspec(dllexport) 
		#endif
    #else
        #define CLIENT_NET_API  __declspec(dllimport)
    #endif

    #define CALLBACK        __stdcall
    #define CALL_METHOD     __stdcall  ///__cdecl

    #define INT64           __int64
    #define TP_U64          unsigned __int64
    #define bool    int                             //这里加了一句话
    #ifndef LLONG
        #ifdef _WIN64
            #define LLONG   INT64
        #else 
            #define LLONG   LONG
        #endif
    #endif

    #ifndef LDWORD
        #ifdef _WIN64
            #define LDWORD  INT64
        #else 
            #define LDWORD  DWORD
        #endif
    #endif

#else    ///non-windows

问题四:C 语言中不能使用引用(&)语法,这是 C++ 语言的特性

C:/Users/c/go/src/VideoForensic/GoldenEyes/videogoplugin/networkscan/include/dhnetsdk.h:73691:148: error: expected ';', ',' or ')' before '&' token
 typedef void (CALLBACK *fSubLogDataCallBack)(LLONG lLogHandle, NET_EM_LOG_QUERY_TYPE emLogType, const DH_DEVICE_LOG_ITEM_EX *pstuLogData, const int& nCount, LDWORD dwUser, void *reserved);
                                                                                                                                                    ^
C:/Users/c/go/src/VideoForensic/GoldenEyes/videogoplugin/networkscan/include/dhnetsdk.h:76134:64: error: unknown type name 'fSubLogDataCallBack'; did you mean 'fLogDataCallBack'?
 CLIENT_NET_API void CALL_METHOD CLIENT_SetSubscribeLogCallBack(fSubLogDataCallBack pLogDataCB, LDWORD dwUser);
                                                                ^~~~~~~~~~~~~~~~~~~
                                                                fLogDataCallBack

将 const int& nCount 改为 const int* nCount,并确保正确的类型名称定义:

typedef void (CALLBACK *fSubLogDataCallBack)(LLONG lLogHandle, NET_EM_LOG_QUERY_TYPE emLogType, const DH_DEVICE_LOG_ITEM_EX *pstuLogData, const int* nCount, LDWORD dwUser, void *reserved);