搜索
查看: 953|回复: 2

[其他] aardio 调用 go语言/go编译器 演示(已更新)

[复制链接]

160

主题

2471

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
13574
发表于 2018-6-1 05:57:02 | 显示全部楼层 |阅读模式
GO.jpg
go语言自带的jsonrpc 不支持http/websocket,而是使用tcp协议,
所以我刚才在aardio中加了一个库 wsock.tcp.jsonClient 支持与go语言进行jsonrpc调用。

我们先使用go语言编写一个exe文件( 当然你可以把后缀名改为 dll,下面的代码一样可以运行 )
go语言代码如下,注意 go里面{换行写是语法错误 :
package main

import (
   
"fmt"
   
"log"
   
"net"
   
"net/rpc"
   
"net/rpc/jsonrpc"
)

type Args struct {
    X, Y int
}

var listener net.Listener

type Calculator struct{}

func (t *Calculator) Add(args *Args, reply *int)
error {
    *reply = args.X + args.Y
   
return nil
}

func (t *Calculator) Exit(args *int, reply *int)
error {
    listener.Close()
   
return nil
}

func main() {
    cal := new(Calculator)
    server := rpc.NewServer()
    server.Register(cal)

    listener, e := net.Listen(
"tcp", "localhost:0")
   
if e != nil {
        fmt.Printf(
"error:%s\n", e)
        
return
    }
else {
        fmt.Printf(
"%s\n", listener.Addr().String())
    }

   
for {
        
if conn, err := listener.Accept(); err != nil {
            log.Fatal(
"error: " + err.Error())
        }
else {
            go server.ServeCodec(jsonrpc.NewServerCodec(conn))
        }
    }
}

假设上面用go语言生成的exe文件名为gotest.exe,并且是放在当前工程目录下,然后我们用下面的 aardio 代码调用这个 gotest.exe 里的go函数:
import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio调用go语言演示";right=759;bottom=469)
winform.add(
button={cls=
"button";text="调用Go语言的Calculator.Add函数";left=382;top=389;right=678;bottom=427;z=5};
edit={cls=
"edit";left=19;top=12;right=732;bottom=352;edge=1;hscroll=1;multiline=1;vscroll=1;z=1};
editX={cls=
"edit";text="2";left=109;top=392;right=185;bottom=424;edge=1;z=2};
editY={cls=
"edit";text="3";left=238;top=392;right=320;bottom=420;edge=1;z=3};
static={cls=
"static";text="+";left=198;top=395;right=230;bottom=420;align="center";transparent=1;z=4}
)
/*}}*/

import wsock.tcp.jsonClient;
import process.popen;

//gotest.exe是使用go语言编写的exe文件。
var gofile = process.popen("/gotest.exe");
if(!gofile) return winform.msgbox("启动go程序失败");

//读取服务端地址(使用自动分配的空闲端口避免冲突)
var url = gofile.read();
if( !url || string.startWith(url,"error:")  ) return winform.msgbox("启动go程序失败");

//连接go语言服务端
var go = wsock.tcp.jsonClient(url)
winform.edit.print(
"已连接到go程序",url);

winform.button.oncommand =
function(id,event){
   
   
//调用go语言提供的函数
    var rep = go.Calculator.Add({
        X =
tonumber(winform.editX.text);
        Y =
tonumber(winform.editY.text);
    } )
     
   
if( rep[["result"]] ){  
        winform.edit.print(
"调用成功", rep.result )
    }
   
else {
        winform.edit.print( rep[[
"error"]] )
    }
}

winform.show()
win.loopMessage();

//通知go程序退出
go.Calculator.Exit(0);





回复

使用道具 举报

160

主题

2471

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
13574
 楼主| 发表于 2018-6-1 06:48:49 | 显示全部楼层

附:调用Go语言编译器例子

import console;
import golang;

var go = golang();

go.runCode(
"/hello.go",`
package main
import "fmt"
func main() {
    fmt.Println("hello world")
}`
)

console.pause();


回复

使用道具 举报

160

主题

2471

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
13574
 楼主| 发表于 2018-6-13 17:18:45 | 显示全部楼层
最新版golang扩展库已支持自动下载配置Go编译器。
Go最新版已经支持调用生成DLL文件(需要调用gcc),在aardio中可以直接调用Go生成的DLL文件(使用cdecl调用约定),下面是调用Go编译器生成DLL的演示。

下面看演示:
import console;
import golang;

//创建Go编译器
var go = golang();

//Go源码与字符串都是UTF-8编码,跟aardio一样很方便
string.save("/hello.go",`
package main

import "C"
import "fmt"

//export SayHello
func SayHello(name string) {
    fmt.Printf("Go says: %s!\n", name)
}

func main() {
   //DLL入口函数,没有也要写个空的
} `
)

//编译Go源码生成DLL文件
go.buildShared("/hello.go","/hello.dll");

//加载Go编译的DLL,注意要指定cdecl调用约定
var dll = raw.loadDll("/hello.dll",,"cdecl");

//直接就可以调用DLL里的函数,不用声明
console.open();
var str = "必须在Go函数名前面加上 export 函数名的注释才能导出函数";
dll.SayHello(str,#str);

console.log( n )
console.pause();
  

Go写DLL要注意一个特别的地方,Go导出函数前必须写一行注释声明导出函数,例如上面的 //export SayHello

Go语言里的字符串GoString是一个结构体,用aardio来表示是这样的:
class goString{
   
ctor( str ){
        
this.s = str;
        
this.n = #str;
    };
    string s;
    addr n;
}

如果是在API函数里传值,一个GoString展开为2个API参数来表示就可以了(一个字符串,后面跟一个字符串长度)
因为aardio传结构体都是传指针,如果用结构体,在Go里面要声明为指针,示例:
import console;
import golang;

//创建Go编译器
var go = golang();

//Go源码与字符串都是UTF-8编码,跟aardio一样很方便
string.save("/hello.go",`
package main

import "C"
import "fmt"

//export SayHello
func SayHello(name *string) {
    fmt.Printf("Go says: %s!\n", *name)
}

func main() {
   //DLL入口函数,没有也要写个空的
} `
)

//编译Go源码生成DLL文件
go.buildShared("/hello.go","/hello.dll");

//加载Go编译的DLL,注意要指定cdecl调用约定
var dll = raw.loadDll("/hello.dll",,"cdecl");

class goString{
   
ctor( str ){
        
this.s = str;
        
this.n = #str;
    };
    string s;
    addr n;
}

//直接就可以调用DLL里的函数,不用声明
console.open();
dll.SayHello( goString(
"必须在Go函数名前面加上 export 函数名的注释才能导出函数") );

console.log( n )
console.pause();
   

需要先安装MinGW( GCC ),
可以下载安装 MinGW-W64: https://sourceforge.net/projects/mingw-w64 这个只能安装在64位系统。
也可以下载安装TDM-GCC: http://tdm-gcc.tdragon.net/download 这个提供支持32位、64位安装包。

golang扩展库会自动搜索MinGW,MinGW-W64,TDM-GCC的安装位置,不需要手动配置。
当然也可以调用golang扩展库提供的addPath函数自己添加gcc.exe所在的目录。

Go生成的文件很大,加上-ldflags "-s -w"参数会小一些,go.buildShared() 已经自动加上这些参数。
编译上面的代码生成的DLL只有1MB多一点,而且可以支持WinXP,不需要依赖外部运行库,还是非常不错的。
而且测试了一下,编译的DLL还能内存加载。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

手机版|未经许可严禁引用或转载本站文章|站长邮箱|aardio.com|aardio官方社区 ( 皖ICP备09012014号 )

GMT+8, 2018-6-25 18:08 , Processed in 0.062500 second(s), 22 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表