如何将 Golang 的 cgo 与 link 到 math.h 的 C 库一起使用?

How do you use Golang's cgo with C libraries that link to math.h?

我目前正在尝试使用 cgoNOVAS C package (an astrometry/astronomy package) 构建一个 Golang 包装器。 NOVAS 本质上是 'installed' 通过将源文件放在您碰巧在其中工作的任何目录中(不存在编译的库文件),因此我相信我需要包含我将使用的 .c 文件(在.go 文件下一个目录的文件夹。

因此,我试图通过创建一个测试 .go 程序来测试它,该程序本身调用 novas.c 中的一个函数。但是,程序无法编译,显然是因为 math.h 中存在多个未定义的函数引用;这很奇怪,因为 math.h 包含在我的 .go 文件和我打算使用的 C 文件中。

go run novasTest.go 
# command-line-arguments
/tmp/go-build681583835/b001/_x002.o: In function `equ2gal':
./Cdist/novas.c:1995: undefined reference to `sincos'
./Cdist/novas.c:1996: undefined reference to `sincos'
./Cdist/novas.c:2033: undefined reference to `atan2'
./Cdist/novas.c:2025: undefined reference to `atan2'
./Cdist/novas.c:2022: undefined reference to `sqrt'
/tmp/go-build681583835/b001/_x002.o: In function `era':
./Cdist/novas.c:3242: undefined reference to `fmod'
./Cdist/novas.c:3242: undefined reference to `fmod'
...(etcetera)

我 运行 在 VirtualBox VM 实例中的 Ubuntu 18.04 (x64) 上。我在这里漏掉了特定的一行吗?

我的 go 程序 看起来像这样:

package main

/*
#include "Cdist/novas.h"
#include "Cdist/novas.c"
#include "Cdist/novascon.c"
#include "Cdist/nutation.c"
#include <math.h>
*/
import "C"
import "log"  

func main() {
    log.Println("Test of NOVAS function")
    var JulianHigh C.double
    var JulianLow C.double
    ...
    var Z C.double

    // Test values
    JulianHigh = 2458953.5 
    JulianLow = 1.0
    ...
    Z = -1.437110810486059E+03

    vCel := make([]C.double,0) //Create the array to pass to the function.
    vCel = append(vCel, X)
    ...
    vTerFirst := &(vTer[0])

    C.cel2ter(JulianHigh,JulianLow,DeltaT,Method,Accuracy,Option,PolarX,PolarY,vCelFirst,vTerFirst)

    log.Println("C function completed processing.")
}

C 程序太大,无法包含,所以我将改为显示 novas.h 文件和 novas.c 文件的相关部分。

C 文件:

/*
  ...
  novas.c: Main library
  ...
*/

#ifndef _NOVAS_
   #include "novas.h"
#endif

#include <math.h>
... //(other functions follow until the necessary one)
/********cel2ter */

short int cel2ter (double jd_ut_high, double jd_ut_low, double delta_t,
                   short int method, short int accuracy, short int option,
                   double xp, double yp, double *vec1,

                   double *vec2)
/*
------------------------------------------------------------------------

   PURPOSE:
      This function...

请注意,该函数本身依赖于从我包含的其他文件进行调用的函数。

.h 文件:

/*
  ...
  novas.h: Header file for novas.c
  ...
*/

#ifndef _NOVAS_
   #define _NOVAS_

   #ifndef __STDIO__
      #include <stdio.h>
   #endif

   #ifndef __MATH__
      #include <math.h>
   #endif

   #ifndef __STRING__
      #include <string.h>
   #endif
   ...

你需要一个指令来告诉 go linker 到 link 使用 c 的数学库。 header math.h 不包含数学函数的实现:只有它们的声明(第一次近似)。

无论如何,您需要在您的 go 文件的注释中添加这一行:

#cgo LDFLAGS: -lm

-l表示"link with this library",m是C的数学库名称。