我正在编写一个本机库,它使用 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 链接器将其导入两次。
有什么办法可以解决这个问题吗?
不要将实际变量放在 .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",
};