cgo:使用cgo在包中包含C头文件时如何防止“多重定义...”错误?

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

我正在编写一个本机库,它使用 cgo 提供 C api。我有一个包含常量定义的 C 头文件,但是当我使用 cgo 将其包含在包中,然后将此包导入到 go 中的 main 中时,我在构建时收到

multiple definition...
链接器错误:

C:\Users\danie\AppData\Local\Temp\go-link-1146178960\000011.o:C:\Temp\cgo-error\mypackage/errors.h:29: multiple definition of `MYMODULE_ERROR_STRS'; C:\Users\danie\AppData\Local\Temp\go-link-1146178960\000010.o:C:/Temp/cgo-error/mypackage/errors.h:29: first defined here    
collect2.exe: error: ld returned 1 exit status

下面的示例代码使用此答案中给出的错误处理示例: https://stackoverflow.com/a/59221452/1324919

main.go:

package main

import "C"
import "example.com/cgo-error/mypackage"

func main() {}

//export exported_function
func exported_function() {
    mypackage.CallCFunction()
}

mypackage.go(包含 C 头文件):

package mypackage

// #include "errors.h"
import "C"

func CallCFunction() {
    _ = C.mymodule_func1()
}

错误.h:

#ifndef ERRORS_H_
#define ERRORS_H_

/// @brief Error codes for library "mymodule"
typedef enum mymodule_error_e
{
    /// No error
    MYMODULE_ERROR_OK = 0,
    MYMODULE_ERROR_INVARG,
    MYMODULE_ERROR_NOMEM,
    MYMODULE_ERROR_MYERROR,
    MYMODULE_ERROR_COUNT,
} mymodule_error_t;

// Array of strings to map enum error types to printable strings
const char *const MYMODULE_ERROR_STRS[] =
    {
        "MYMODULE_ERROR_OK",
        "MYMODULE_ERROR_INVARG",
        "MYMODULE_ERROR_NOMEM",
        "MYMODULE_ERROR_MYERROR",
};

// To get a printable error string
const char *mymodule_error_str(mymodule_error_t err);

// Other functions in mymodule
mymodule_error_t mymodule_func1(void);
mymodule_error_t mymodule_func2(void);
mymodule_error_t mymodule_func3(void);

#endif

错误.c:

#include "errors.h"
#include <stdio.h>

/// @brief      Function to get a printable string from an enum error type
/// @param[in]  err     a valid error code for this module
/// @return     A printable C string corresponding to the error code input above, or NULL if an invalid error code
///             was passed in
const char *mymodule_error_str(mymodule_error_t err)
{
    const char *err_str = NULL;

    // Ensure error codes are within the valid array index range
    if (err >= MYMODULE_ERROR_COUNT)
    {
        goto done;
    }

    err_str = MYMODULE_ERROR_STRS[err];

done:
    return err_str;
}

// Let's just make some empty dummy functions to return some errors; fill these in as appropriate for your
// library module

mymodule_error_t mymodule_func1(void)
{
    return MYMODULE_ERROR_OK;
}

mymodule_error_t mymodule_func2(void)
{
    return MYMODULE_ERROR_INVARG;
}

mymodule_error_t mymodule_func3(void)
{
    return MYMODULE_ERROR_MYERROR;
}

在我看来,将头文件包含在

mypackage.go
中并将其包含在
errors.c
中会导致在
mypackage
中导入
main
时,go 链接器将其导入两次。 有什么办法可以解决这个问题吗?

c go linker cgo
1个回答
0
投票

不要将实际变量放在 .h 文件中。将它们放在 C 文件中。

errors.h 文件中:

extern const char *const MYMODULE_ERROR_STRS[];

以及 errors.c: 文件中的实际定义:

const char *const MYMODULE_ERROR_STRS[] =
    {
        "MYMODULE_ERROR_OK",
        "MYMODULE_ERROR_INVARG",
        "MYMODULE_ERROR_NOMEM",
        "MYMODULE_ERROR_MYERROR",
};
© www.soinside.com 2019 - 2024. All rights reserved.