go编译成dll:
go build -buildmode=c-shared -o dll文件名.dll go文件名.go
注意:编译成功后会在本地目录.生成一个dll和相应的.h头文件,其中描述的是go的数据类型在c中的对应.调用时建议引用.
简化版的加载dll:
gcc -s -w xxx.c xxx.dll -o xxx
-s -w压缩选项,可不要(顺便提一句,go编译的时候加入-ldflags="-s -w"
可以减小体积).
手头有个项目要完成c的中文处理,需要用到中文字符切片,但是c没有明确给出方法,而且文件编码很头疼.联想到golang不需要在意文件编码这一优势,所以需要互访.
实验1:通过调研go的函数来屏幕输出实现细节上手dll函数:
package mainimport "fmt"import "C"//export Printffunc Printf(format, str string) { fmt.Printf(format, str)}func main(){}
要导出的函数前面一行必须一个空格不加一个不少的格式,写上:
//export 函数名
然后函数主体部分,都是正常的.然后必须有个main函数,不会被导出,但是编译器需要它,这是必须的,尤其是"package main"导致了必须存在main()函数
然后运行编译命令,生成:
下面写c语言调用代码:
#include "eee.h"#include <stdio.h>int main() { char fstr[]="哈哈哈中文输出,数据来源:c文件[%s]\n"; GoString fm = {fstr, sizeof(fstr)}; char *v = malloc(33); file *fp = fopen("a.txt", "r"); if (!fp) {return;} fread(v, sizeof(char), 30, fp); GoString values={v,30}; Printf(fm, values);}
编译运行
golang可以直接访问c的内存,毕竟a.txt的内容是保存在用c语言开辟的空间里.
实验2:go返回非指针类型给cgo:
//export Cutfunc Cut(s string, i int) string{ s1 := string([]rune(s)[i]) print("in go1", s1) print("int go2", i) return s1}
(勉强挤出)go不要直接返回非指针结果,这回导致不可预料结果.解决方案[理论上]取结构体地址,把地址返回给c
实验3:go返回指针返回*C.char
试试呢?
//export Cutfunc Cut(s string, i int) *C.char{ s1 := string([]rune(s)[i]) print("in go1", s1) print("int go2", i) return C.CString(s1)}
char *vvs = Cut(values, 1); GoString vv={vvs, strlen(vvs)+1}; Printf(fm, vv);
结论[反证法]直接返回指针是没问题的,c也可以直接访问.
[题外话]我又加了一句printf("%s\n")
,也没问题
c->go传参只要按照go提供的数据格式,就基本没问题;
go->c安全的话应该返回指针而不是数据内容.
以上是内存溢出为你收集整理的记录下go和c互访注意事项全部内容,希望文章能够帮你解决记录下go和c互访注意事项所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)