Delphi 调用 go dll
Pykill 写入
Delphi 调用 go dll
只需要用两个C.GoString C.CString
我只是为自己写的一个http 调用,主要是go在调用非常稳定,不会存在证书,不证书,连接过多被报错,正常情况下的网络报错问题,在这里同时分享go的dll 和delphi 调用,里面有string ,bytes的多方便调用 这里只测试get, post 还没测试就跑来发布了
还要注意下,这里是以32编译的dll
这下面是编译命令
set GOARCH=386
set CGO_ENABLED=1
go build -buildmode=c-shared -o Vhttp.dll main.go
go 的dll 代码
package main
import (
"bytes"
"encoding/json"
"fmt"
"github.com/tidwall/gjson"
"github.com/zetamatta/go-windows-dbg"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/encoding/unicode"
"golang.org/x/text/transform"
"io/ioutil"
"net"
"net/http"
"sync"
"time"
)
import "C"
var client = http.Client{}
var syncpol sync.Pool
func init() {
//这里初始化连接客户端,非常稳定
client = http.Client{Timeout: 5 * time.Second,
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 1 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
MaxIdleConnsPerHost: 8,
IdleConnTimeout: 120 * time.Second,
}}
syncpol = sync.Pool{}
dbg.Println("init ok")
}
func main() {
}
func Decode(s *C.char)string {
cs16 := C.GoString(s)
//s8,_ := code16to8.String(cs16)
return cs16
}
func Encode(s string)*C.char {
//s16,_ := code8to16.String(s)
var kms string
ls := syncpol.Get()
if ls == nil {
kms = s
} else {
kms = ls.(string)
}
syncpol.Put(kms)
return C.CString(s)
}
func writeerror(err string)string {
vs := map[string]interface{}{"error":err}
buf,_ := json.Marshal(vs)
return string(buf)
}
//这里的export 是必须要加上这是对外可见
//export SHChar
func SHChar(sh *C.char)*C.char {
dbg.Println(9,sh)
return sh
}
//export SH1Char
func SH1Char(sh *C.char)*C.char{
vms := Decode(sh)
dbg.Println(3,vms )
kms := "SH1Chia"
//return C.CString(kms)
return Encode(kms)
}
func vlog(s string) {
dbg.Println(s)
}
//export Httpurl
func Httpurl(styp int, url,sh , buf *C.char )*C.char {
var surl string
var ssh string
var sbuf string
if url != nil {
surl = Decode(url)
}
if sh != nil {
ssh = Decode(sh)
}
if buf != nil {
sbuf = Decode(buf)
}
if surl == "" {
s := writeerror("url is emtpy")
return Encode(s)
}
var req *http.Request
var err error
if sbuf != "" {
sby:= bytes.NewBuffer([]byte(sbuf))
req,err = http.NewRequest("GET",surl,sby)
if err != nil {
s := writeerror(err.Error())
return Encode(s)
}
} else {
req,err = http.NewRequest("GET",surl,nil)
if err != nil {
s := writeerror(err.Error())
return Encode(s)
}
}
if ssh != "" {
sher := gjson.Get(ssh,"header")
if sher.Exists() {
for k, v := range sher.Map() {
req.Header.Set(k, v.Value().(string))
}
}
}
switch styp {
case 1: //get
{
req.Method = "GET"
}
case 2://post
{
req.Method = "POST"
}
case 3://head
{
req.Method = "HEAD"
}
case 4:
{
req.Method = "PUT"
}
case 5:
{
req.Method = "DELETE"
}
case 6:
{
req.Method = "OPTIONS"
}
case 7:
{
req.Method = "TRACE"
}
case 8:
{
req.Method = "PATCH"
}
default:
{
return Encode("stype is error")
}
}
reqs,err := client.Do(req)
if err != nil {
return Encode(err.Error())
}
smap := map[string]interface{}{}
vbuf,err := json.Marshal(reqs.Header)
if err != nil {
return Encode(err.Error())
}
smap["header"] = string(vbuf)
vbuf ,err = ioutil.ReadAll(reqs.Body)
if err != nil {
return Encode(err.Error())
}
var sss string
for _, v := range vbuf{
sss += fmt.Sprintf(" %d", v)
}
smap["data"] = sss
kbuf,_ := json.Marshal(smap)
return Encode(string(kbuf))
}
这里是delphi 代码
dll 接口代码
unit VHTTP;
interface
uses
Winapi.Windows, system.Classes, system.SyncObjs, system.Types, System.SysUtils;
type
TVHTTPDLL = Class
private
Mydll: HMODULE;
FError: string;
Finit: Boolean;
procedure SetError(const Value: string);
protected
procedure init;
public
constructor Create;
destructor Destroy; override;
property Error: string read FError write SetError;
function CSHChar(s: PAnsiChar): PAnsiChar;
function CSH1Char(s: PAnsiChar): PAnsiChar;
function CHttpurl(stype: Integer; url, header, buf: PAnsiChar): PAnsiChar;
End;
const
Vhttpdllname = 'Vhttp32.dll';
implementation
{ TVHTTPDLL }
var
SHChar: function(s: PAnsiChar): PAnsiChar; cdecl;
SH1Char: function(s: PAnsiChar): PAnsiChar; cdecl;
Httpurl: function(stype: Integer; url, header, buf: PAnsiChar): PAnsiChar; cdecl;
function TVHTTPDLL.CHttpurl(stype: Integer; url, header, buf: PAnsiChar): PAnsiChar;
begin
Result := Httpurl(stype, url, header, buf)
end;
constructor TVHTTPDLL.Create;
begin
Self.init;
end;
function TVHTTPDLL.CSH1Char(s: PAnsiChar): PAnsiChar;
begin
Result := SH1Char(s);
end;
function TVHTTPDLL.CSHChar(s: PAnsiChar): PAnsiChar;
begin
Result := SHChar(s);
end;
destructor TVHTTPDLL.Destroy;
begin
if Finit then
begin
freeLibrary(Mydll);
end;
end;
procedure TVHTTPDLL.init;
begin
FError := '';
Mydll := LoadLibrary(Vhttpdllname);
if Mydll <> 0 then
begin
@SHChar := GetProcAddress(Mydll, 'SHChar');
@SH1Char := GetProcAddress(Mydll, 'SH1Char');
@Httpurl := GetProcAddress(Mydll, 'Httpurl');
if not Assigned(SHChar) and not Assigned(SH1Char) and not Assigned(Httpurl) then
begin
raise Exception.Create('init Vhttp error');
Exit;
end;
Finit := True;
Exit;
end;
FError := 'loadlibrayf error';
Exit;
end;
procedure TVHTTPDLL.SetError(const Value: string);
begin
FError := Value;
end;
end.
窗口代码
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Buttons, VHTTP, Vcl.StdCtrls, qjson;
type
TForm1 = class(TForm)
SpeedButton1: TSpeedButton;
mo1: TMemo;
SpeedButton2: TSpeedButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure SpeedButton1Click(Sender: TObject);
procedure SpeedButton2Click(Sender: TObject);
private
{ Private declarations }
FVhttp: TVHTTPDLL;
procedure Log(s: string);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
FVhttp := TVHTTPDLL.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FVhttp.Free;
end;
procedure TForm1.Log(s: string);
var
vs: string;
begin
vs := FormatDateTime('dd hh:nn:ss', Now) + s;
mo1.Lines.Insert(0, vs);
end;
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
Log(FVhttp.CSHChar(PAnsiChar('delphi')));
Log(FVhttp.CSH1Char(PAnsiChar('delphi1')));
end;
function VToByte(s: string): TBytes;
var
sts: TStringList;
i: integer;
begin
sts := TStringList.Create;
try
sts.Delimiter := ' ';
sts.DelimitedText := s;
SetLength(result, sts.Count);
for i := 0 to sts.Count - 1 do
begin
result[i] := strtoint(sts[i]);
end;
finally
sts.Free;
end;
end;
procedure TForm1.SpeedButton2Click(Sender: TObject);
var
url, header, sbuf: PAnsiChar;
vds, vhex, sutf8: string;
tjs: TQjson;
vbuf: TBytes;
sts: TStringStream;
begin
url := 'http://time.tianqi.com/';
vds := FVhttp.CHttpurl(1, url, '', '');
tjs := TQjson.Create;
try
tjs.Parse(vds);
vhex := tjs.ForceName('data').AsString;
if vhex <> '' then
begin
vbuf := VToByte(vhex);
sts := TStringStream.Create('', TEncoding.UTF8);
try
sts.Write(vbuf, 0, length(vbuf));
Log(sts.DataString);
finally
sts.Free;
end;
end;
finally
tjs.Free;
end;
end;
end.
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)