C. 前向声明
为了在Go代码里能够正确的识别我们的True函数,我们需要写一个前向声明。如果没有前向声明,Go编译器不知道这个函数的存在。这个与首字母大小写使得函数在包外面是否可见没有关联
前向声明方式如下:
[cpp] view plaincopy
// True always returns true.
func True() bool
前向声明包含如下信息:函数True没有参数并且返回一个bool类型的值。因为这是个普通的Go函数,你可以在前面添加注释,这样可以用godoc显示出来(C函数里的注释不会被godoc显示)
D. 向C代码传递参数
下面将给出一个函数Max,他将返回两个int参数中最大的那个
[plain] view plaincopy
void ·Max(intptr a, intptr b, intptr res) {
res = a > b ? a : b;
FLUSH(&res);
}
Max和前面的True函数相似,前面两个参数是函数参数,最后一个参数是返回值。函数的返回值并不是一定要命名为res,只是标准库里一个常用的用法而已
a和b是intptr类型的,这个是c里等价于Go里的平台相关的int类型(x86:int32 x64:int64)
Max的前向声明如下,可以通过这个例子看看Go的参数和返回值与C里的参数的对应关系
[plain] view plaincopy
// Max returns the maximum of two integers.
func Max(a, b int) int
E. 传递地址
前面两个例子,我们传递两个参数给函数并且把拷贝通过堆栈返回。Go的函数调用是值传递,调用C函数也是如此
最后一个例子我们将传递某个变量的指针给C函数,并通过指针改变这个值
[plain] view plaincopy
void ·Inc(intptr* addr) {
*addr+=1;
USED(addr);
}
Inc函数得到了a的指针,解引用并且+1,USE宏和FLUSH作用类似
前向声明如下:
[plain] view plaincopy
// Inc increments the value of the integer add address p.
func Inc(p *int)
F. 所有代码
测试代码和测试结果如下:
ccode.c
[cpp] view plaincopy
#include "runtime.h" // required for go types like bool and intptr
// The interpunkt indicates that the function belongs to the current
// namespace. Without the interpunkt, the function would be defined in
// the global C namespace, inaccessible to your Go package and
// potentially conflicting with another C function.
void ·True(bool res) {
res = true;
FLUSH(&res);
}
// intptr is equivalent to Go's arch specific int type
void ·Max(intptr a, intptr b, intptr res) {
res = a > b ? a : b;
FLUSH(&res);
}
void ·Inc(intptr* addr) {
*addr+=1;
USED(addr);
}
ccode.go
[plain] view plaincopy
package ccode
// True always returns true.
func True() bool
// Max returns the maximum of two integers.
func Max(a, b int) int
// Inc increments the value of the integer add address p.
func Inc(p *int)