gitee.com/haifengat/gotap_dipper@v0.0.4-0.20231212021028-041a6fa876e5/generate/run.go (about) 1 package generate 2 3 import ( 4 "fmt" 5 "regexp" 6 "strings" 7 "text/template" 8 ) 9 10 func genQuote() { 11 fnFuncs, onFuncs := getFuncsQuote() 12 writeTmpl("quote.h.tpl", "../c/quote.h", map[string]any{"On": onFuncs, "Fn": fnFuncs}, template.FuncMap{ 13 "trim": func(s string) string { 14 return strings.TrimLeft(s, "*") 15 }, 16 }) 17 writeTmpl("quote.cpp.tpl", "../c/quote.cpp", map[string]any{"On": onFuncs, "Fn": fnFuncs}, template.FuncMap{ 18 "trim": func(s string) string { 19 return strings.TrimLeft(s, "*") 20 }, 21 }) 22 23 // golang 24 writeTmpl("quote_lnx.go.tpl", "../go/quote/quote_lnx.go", map[string]any{"On": onFuncs, "Fn": fnFuncs}, funcMapTradeFnQuote, funcMapTradeOnQuote) 25 } 26 27 // 调用函数,参数类型转换 28 var funcMapTradeFnQuote = template.FuncMap{ 29 // 去掉变量前的 * 30 "trim": func(s string) string { return strings.Trim(s, "*") }, 31 // 在 trade_lnx.go 中的 C 头使用 32 // C++的自定义类型,还原为 C++ 原始类型 33 // 特别处理 ClientOrderNo -> char *, 正常处理会变成 char** 34 "CHeaderBaseType": func(typ, name string) string { 35 typ = strings.ReplaceAll(typ, "const ", "") 36 if strings.HasPrefix(typ, "TapAPI") || strings.HasPrefix(typ, "const TapAPI") { // struct 37 return "struct " + typ 38 } 39 if strings.HasPrefix(typ, "TAPISTR_") || strings.HasPrefix(typ, "TAPSTR_") { 40 return "char *" 41 } 42 switch typ { 43 case "ITapQuoteAPINotify": // spi 44 return "void " 45 case "TAPIRightIDType", "TAPIINT32": 46 return "int" 47 case "TAPIUINT32": 48 return "unsigned int" 49 case "TAPICHAR", "const TAPICHAR", "TAPIYNFLAG": 50 return "char" 51 case "TAPIUINT16": 52 return "unsigned short" 53 case "TAPIDATE": 54 return "char *" 55 default: 56 fmt.Println(typ) 57 return typ 58 } 59 }, 60 // go 请求函数参数 61 // 转换为 go 的类型 62 "C2Go": func(typ, name string) string { 63 typ = strings.ReplaceAll(typ, "ITapTrade::", "") // On 函数类型中多出的前缀 64 typ = strings.ReplaceAll(typ, "const", "") 65 typ = strings.TrimSpace(typ) 66 switch typ { 67 case "ITapQuoteAPINotify": // spi 68 return strings.Trim(name, "*") + " unsafe.Pointer" 69 case "TAPICHAR": // char* -> string 70 return strings.Trim(name, "*") + " string" 71 } 72 // *TAPISTR_50 73 if strings.Contains(name, "*") { 74 if !strings.Contains(typ, "TAPISTR_") { // 双重指针,只传递一层, 可能有问题!!! 75 typ = "*" + typ 76 } 77 name = strings.Trim(name, "*") 78 } 79 // 重命名的 struct 80 if strings.Contains(typ, "*") { 81 if reqTpy, ok := Rsp2ReqMv[strings.Trim(typ, "*")]; ok { 82 typ = "*" + reqTpy 83 } 84 } 85 return name + " " + typ 86 }, 87 // go 请求函数中调用 C 函数, 参数需转为 C 类型, 作为 C 函数的参数 88 // TAPIUINT32 => C.int 89 "Go2C": func(typ, name string) string { 90 typ = strings.ReplaceAll(typ, "const ", "") 91 typ = strings.TrimSpace(typ) 92 name = strings.Trim(name, "*") 93 if strings.HasPrefix(typ, "TapAPI") { 94 // 重命名的 struct 95 if reqTpy, ok := Rsp2ReqMv[typ]; ok { 96 typ = reqTpy 97 } 98 return fmt.Sprintf("(*C.struct_%s)(unsafe.Pointer(%s))", typ, name) 99 } 100 // TAPISTR_10 -> [11]byte 101 if strings.HasPrefix(typ, "TAPISTR_") || strings.HasPrefix(typ, "TAPSTR_") { 102 // 转换后的 & 会变成 & 103 s := fmt.Sprintf("(*C.char)(unsafe.Pointer(&%s[0]))", name) 104 return s 105 } 106 switch typ { 107 case "TAPICHAR": 108 return fmt.Sprintf("C.CString(%s)", name) 109 case "TAPIUINT16": 110 return fmt.Sprintf("C.ushort(%s)", name) 111 case "TAPIUINT32": 112 return fmt.Sprintf("(*C.uint)(unsafe.Pointer(%s))", name) 113 case "TAPIRightIDType": // int 114 return fmt.Sprintf("C.int(%s)", name) 115 } 116 fmt.Println(typ, " ", name) 117 return name 118 }, 119 } 120 121 // 响应函数定义, 参数类型转换 122 var funcMapTradeOnQuote = template.FuncMap{ 123 // 响应函数变量的定义 124 // OnConnected func(hsotAddr string) 125 "DefineVar": func(typ, name string) string { 126 typ = strings.ReplaceAll(typ, "ITapTrade::", "") 127 typ = strings.ReplaceAll(typ, "const", "") 128 typ = strings.TrimSpace(typ) 129 if strings.Contains(typ, "TAPISTR_") { 130 typ = "string" 131 } else if strings.Contains(name, "*") { // name 中有* 指针 132 name = strings.Trim(name, "*") 133 if reqTpy, ok := Rsp2ReqMv[typ]; ok { 134 typ = reqTpy 135 } 136 typ = "*" + typ 137 } else { 138 switch typ { 139 case "TAPIDATE": // 原定义为 [n]byte 140 typ = "string" 141 } 142 } 143 return name + " " + typ 144 }, 145 // 响应函数声明中的参数, 由 c 转换为 cgo 类型 146 "CCB": func(typ, name string) string { 147 typ = strings.ReplaceAll(typ, "ITapTrade::", "") // On 函数类型中多出的前缀 148 typ = strings.ReplaceAll(typ, "const ", "") 149 // 回调函数里的 struct 参数 150 if strings.Contains(typ, "TapAPI") { 151 // 重命名的 struct 152 if reqTpy, ok := Rsp2ReqMv[typ]; ok { 153 typ = reqTpy 154 } 155 typ = fmt.Sprintf("*C.struct_%s", strings.TrimSpace(strings.Trim(typ, "*"))) 156 } else if strings.Contains(typ, "TAPISTR_") { 157 typ = "*C.char" 158 } else { 159 switch typ { 160 case "TAPIYNFLAG": 161 typ = "C.char" 162 case "TAPIINT32": 163 typ = "C.int" 164 case "TAPIUINT32": 165 typ = "C.uint" 166 case "bool": 167 typ = "C._BOOL" 168 case "int": 169 typ = "C.int" 170 case "TAPIDATE": 171 typ = "*C.char" 172 } 173 } 174 name = strings.Trim(name, "*") 175 return name + " " + typ 176 }, 177 // C的函数参数转为go类型 178 "cgo": func(typ, name string) string { 179 typ = strings.ReplaceAll(typ, "ITapTrade::", "") 180 typ = strings.ReplaceAll(typ, "const", "") 181 typ = strings.TrimSpace(typ) 182 if strings.Contains(typ, "TAPISTR_") { 183 return fmt.Sprintf("GBK(%s)", name) 184 } else if strings.Contains(name, "*") { // name 中有* 指针 185 // (*TapAPITradeLoginRspInfo)(unsafe.Pointer(loginRspInfo)) 186 name = strings.Trim(name, "*") 187 // 类型替代 188 if reqTpy, ok := Rsp2ReqMv[typ]; ok { 189 typ = reqTpy 190 } 191 return fmt.Sprintf("(*%s)(unsafe.Pointer(%s))", typ, name) 192 } else { 193 switch typ { 194 case "TAPIDATE": 195 return fmt.Sprintf("GBK(%s)", name) 196 } 197 } 198 return fmt.Sprintf("%s(%s)", typ, name) 199 }, 200 } 201 202 // getFuncsQuote 获取行情调用/响应函数 203 func getFuncsQuote() (fn []Func, on []Func) { 204 str := readFile("TapQuoteAPI.h") 205 // virtual void TAP_CDECL OnRtnContactInfo(ITapTrade::TAPIINT32 errorCode, ITapTrade::TAPIYNFLAG isLast, const ITapTrade::TAPISTR_40 ContactInfo) = 0; 206 re := regexp.MustCompile(`virtual.*TAP_CDECL (\w+)\(([^)]*)`) 207 matchs := re.FindAllStringSubmatch(str, -1) 208 onFuncs := make([]Func, 0) 209 fnFuncs := make([]Func, 0) 210 // 取响应函数列表 211 for _, m := range matchs { 212 funcName := m[1] 213 params := m[2] 214 fn := Func{ 215 FuncName: funcName, 216 } 217 // virtual void TAP_CDECL OnRtnCombinePosition(const ITapTrade::TapAPICombinePositionInfo *info) {}; 218 // int days 为何会被漏掉? 在`?:ITapTrade|const ITapTrade`中增加 最后一个字段'|in' 219 // virtual void TAP_CDECL OnExpriationDate(ITapTrade::TAPIDATE date, int days) = 0; 220 // virtual void TAP_CDECL OnRspRequestVertificateCode(ITapTrade::TAPIUINT32 sessionID, ITapTrade::TAPIINT32 errorCode, const TapAPIRequestVertificateCodeRsp *rsp) = 0; 221 // virtual void TAP_CDECL OnRspQryPositionSummary(TAPIUINT32 sessionID, TAPIINT32 errorCode, TAPIYNFLAG isLast, const TapAPIPositionSummary *info) = 0; 222 re = regexp.MustCompile(`((?:ITapTrade|const ITapTrade|in|const TapAPI|TAP)[\w:]+)\s+(\*?\w+)`) 223 fields := re.FindAllStringSubmatch(params, -1) 224 for _, p := range fields { 225 fn.Params = append(fn.Params, struct { 226 Type string 227 Name string 228 }{ 229 Type: p[1], 230 Name: p[2], 231 }) 232 } 233 if strings.HasPrefix(funcName, "On") { 234 onFuncs = append(onFuncs, fn) 235 } 236 } 237 238 fmt.Println("响应函数数量: ", len(onFuncs)) 239 240 // 取请求函数列表 241 for _, m := range matchs { 242 funcName := m[1] 243 // 只处理 非 On 开头 244 if strings.HasPrefix(funcName, "On") { 245 continue 246 } 247 params := m[2] 248 fn := Func{ 249 FuncName: funcName, 250 } 251 // virtual ITapTrade::TAPIINT32 TAP_CDECL VerificateUnFreezeInfo(TAPIUINT32 *sessionID, const TapAPIVerifyIdentityReq *qryReq) = 0; 252 // virtual ITapTrade::TAPIINT32 TAP_CDECL QryPositionSummary(ITapTrade::TAPIUINT32 *sessionID, const ITapTrade::TapAPIPositionQryReq *qryReq) = 0; 253 re = regexp.MustCompile(`((?:T|const T|I|const I)[\w:]+)\s+(\*?\s?\w+)`) 254 fields := re.FindAllStringSubmatch(params, -1) 255 for _, p := range fields { 256 fn.Params = append(fn.Params, struct { 257 Type string 258 Name string 259 }{ 260 // 去掉 参数中的 namespace 261 Type: strings.ReplaceAll(p[1], "ITapTrade::", ""), 262 Name: p[2], 263 }) 264 } 265 fnFuncs = append(fnFuncs, fn) 266 } 267 268 fmt.Println("请求函数数量: ", len(fnFuncs)) 269 return fnFuncs, onFuncs 270 } 271 272 func genStructCgoQuote() { 273 structs := getStructsCQuote() 274 writeTmpl("struct.cgo.tpl", "../go/quote/struct_cgo.h", structs, template.FuncMap{ 275 "cgo": func(typ, name string) string { 276 if strings.HasPrefix(typ, "TAPISTR_") { 277 return fmt.Sprintf("char %s[%s]", name, typ[8:]) 278 } else if (strings.HasPrefix(typ, "TapAPI") || strings.HasPrefix(typ, "TAPI")) && strings.HasSuffix(typ, "Type") { // TapAPIApplyStatusType TAPIHedgeFlagType 279 typ = "char" 280 } else { 281 switch typ { 282 case "TapAPICommodity", "TapAPINewOrder", "TapAPIContract": // 本来就是 struct 283 typ = "struct " + typ 284 case "TAPICHAR", "TAPIYNFLAG", "TAPILOGLEVEL", "TAPIAccountState", "TAPIORDERACT": 285 typ = "char" 286 case "TAPIUINT32": 287 typ = "unsigned int" 288 case "TAPIINT32": 289 typ = "int" 290 case "TAPIQVOLUME": // uint64 291 typ = "unsigned long long" 292 case "TAPIQDIFF": // int64 293 typ = "long long" 294 case "TAPIREAL64", "TAPIQPRICE": 295 typ = "double" 296 case "TAPIDTSTAMP": 297 return fmt.Sprintf("char %s[24]", name) 298 case "TAPIAUTHCODE": 299 return fmt.Sprintf("char %s[513]", name) 300 case "TAPIMACTYPE": 301 return fmt.Sprintf("char %s[13]", name) 302 case "TAPIDATE": 303 return fmt.Sprintf("char %s[11]", name) 304 case "TAPIDATETIME": 305 return fmt.Sprintf("char %s[20]", name) 306 case "TAPICommodityType": 307 typ = "char" 308 default: 309 fmt.Println(typ) 310 } 311 } 312 return typ + " " + name 313 }, 314 }) 315 } 316 317 func genStructGoQuote() { 318 structs := getStructsCQuote() 319 writeTmpl("struct_quote.go.tpl", "../go/quote/structs.go", structs) 320 } 321 322 // getStructsC 获取 C 的 struct 定义 323 func getStructsCQuote() []Struct { 324 // 读取文件内容 325 str := readFile("TapAPICommDef.h", "TapQuoteAPIDataType.h") 326 327 re := regexp.MustCompile(`struct\s*(\w*)\s*{([^}]*)}`) // 分成struct的注释,名称,字段两部分 328 matchs := re.FindAllStringSubmatch(string(str), -1) 329 330 structs := make([]Struct, 0) 331 for _, m := range matchs { 332 s := Struct{ 333 Name: m[1], 334 } 335 // 转换字段 336 reField := regexp.MustCompile(`(\w+)\s+([^;]+);\s+///(.*)`) 337 for _, f := range reField.FindAllStringSubmatch(m[2], -1) { 338 s.Fields = append(s.Fields, struct { 339 Name string 340 Type string 341 Comment string 342 }{ 343 Name: f[2], 344 Type: f[1], 345 Comment: f[3], 346 }) 347 } 348 structs = append(structs, s) 349 } 350 fmt.Println("struct 数量: ", len(structs)) 351 return structs 352 } 353 354 // genDataTypeGo 生成 go 的数据类型 355 func genDataTypeGoQuote() { 356 dataTypes := getDataTypeCQuote() 357 // 模板生成(New后的名字要用完整的文件名) 358 writeTmpl("datatype_quote.go.tpl", "../go/quote/datatype.go", dataTypes, template.FuncMap{ 359 "typeTrans": func(src string) string { 360 switch src { 361 case "char": 362 return "string" 363 case "int": 364 return "int" 365 case "long", "long long": 366 return "int64" 367 case "double": 368 return "float64" 369 case "unsigned int": 370 return "uint" 371 case "unsigned long", "unsigned long long": // TAPIUINT64 372 return "uint64" 373 case "unsigned short": 374 return "uint16" 375 case "unsigned char": 376 return "uint8" 377 } 378 return src 379 }, 380 }) 381 } 382 383 // getDataTypeC 获取 C 中数据类型的定义 384 func getDataTypeCQuote() []DataType { 385 // 读取文件内容 386 str := readFile("TapAPICommDef.h", "TapQuoteAPIDataType.h") 387 388 /*//! 看涨看跌标示 389 typedef TAPICHAR TAPICallOrPutFlagType;*/ 390 // => type TAPICallOrPutFlagType byte 391 //! 长度为10的字符串 392 // typedef char TAPISTR_10[11]; 393 // => type TAPISTR_10 [11]byte 394 re := regexp.MustCompile(`//!?\s*(.*)\n\s?typedef\s+(\w+\s?\w+)\s+([\w[]+)`) 395 defines := re.FindAllStringSubmatch(str, -1) 396 397 /* //! 买权 398 const TAPICallOrPutFlagType TAPI_CALLPUT_FLAG_CALL = 'C';*/ 399 // const TAPI_CALLPUT_FLAG_CALL TAPICallOrPutFlagType = 'C' 400 reConst := regexp.MustCompile(`//!\s+(.*)\n\s?const\s+(\w+)\s+(\w+)\s+=\s?\'(\w)\'`) 401 consts := reConst.FindAllStringSubmatch(str, -1) 402 403 dataTypes := make([]DataType, 0) 404 for _, def := range defines { 405 // typedef char TAPISTR_10[11]; 406 comment := def[1] 407 srcType := def[2] // c++ 类型 408 typeName := def[3] // TAPISTR_10[11 ** 没有右括号 409 if strings.Contains(typeName, "[") { // char[nn] 410 srcType = fmt.Sprintf("[%s]byte", strings.Split(typeName, "[")[1]) 411 typeName = strings.Split(typeName, "[")[0] 412 } 413 dt := DataType{ 414 CType: srcType, 415 TypeName: typeName, 416 Comment: comment, 417 } 418 for _, c := range consts { 419 comment := c[1] 420 constType := c[2] 421 constName := c[3] 422 constValue := c[4] 423 if strings.Contains(constType, typeName) { 424 dt.Const = append(dt.Const, struct { 425 TypeName string 426 Name string 427 Value string 428 Comment string 429 }{ 430 TypeName: typeName, 431 Name: constName, 432 Value: constValue, 433 Comment: comment, 434 }) 435 } 436 } 437 dataTypes = append(dataTypes, dt) 438 } 439 440 fmt.Println("数量: ", len(dataTypes)) 441 return dataTypes 442 } 443 444 // genTrade 生成 trade.h trade.cpp trade.go 445 func genTrade() { 446 fnFuncs, onFuncs := getFuncs() 447 // C++ 448 writeTmpl("trade.h.tpl", "../c/trade.h", map[string]any{"On": onFuncs, "Fn": fnFuncs}, template.FuncMap{ 449 "trim": func(s string) string { 450 return strings.TrimLeft(s, "*") 451 }, 452 }) 453 writeTmpl("trade.cpp.tpl", "../c/trade.cpp", map[string]any{"On": onFuncs, "Fn": fnFuncs}, template.FuncMap{ 454 "trim": func(s string) string { 455 return strings.TrimLeft(s, "*") 456 }, 457 }) 458 459 // golang 460 writeTmpl("trade_lnx.go.tpl", "../go/lnx/trade_lnx.go", map[string]any{"On": onFuncs, "Fn": fnFuncs}, funcMapTradeFn, funcMapTradeOn) 461 } 462 463 type Func struct { 464 FuncName string 465 Params []struct { 466 Type string 467 Name string 468 } 469 } 470 471 func getFuncs() (fn []Func, on []Func) { 472 str := readFile("iTapTradeAPI.h") 473 // virtual void TAP_CDECL OnRtnContactInfo(ITapTrade::TAPIINT32 errorCode, ITapTrade::TAPIYNFLAG isLast, const ITapTrade::TAPISTR_40 ContactInfo) = 0; 474 re := regexp.MustCompile(`virtual.*TAP_CDECL (\w+)\(([^)]*)`) 475 matchs := re.FindAllStringSubmatch(str, -1) 476 onFuncs := make([]Func, 0) 477 fnFuncs := make([]Func, 0) 478 // 取响应函数列表 479 for _, m := range matchs { 480 funcName := m[1] 481 params := m[2] 482 fn := Func{ 483 FuncName: funcName, 484 } 485 // virtual void TAP_CDECL OnRtnCombinePosition(const ITapTrade::TapAPICombinePositionInfo *info) {}; 486 // int days 为何会被漏掉? 在`?:ITapTrade|const ITapTrade`中增加 最后一个字段'|in' 487 // virtual void TAP_CDECL OnExpriationDate(ITapTrade::TAPIDATE date, int days) = 0; 488 // virtual void TAP_CDECL OnRspRequestVertificateCode(ITapTrade::TAPIUINT32 sessionID, ITapTrade::TAPIINT32 errorCode, const TapAPIRequestVertificateCodeRsp *rsp) = 0; 489 // virtual void TAP_CDECL OnRspQryPositionSummary(TAPIUINT32 sessionID, TAPIINT32 errorCode, TAPIYNFLAG isLast, const TapAPIPositionSummary *info) = 0; 490 re = regexp.MustCompile(`((?:ITapTrade|const ITapTrade|in|const TapAPI|TAP)[\w:]+)\s+(\*?\w+)`) 491 fields := re.FindAllStringSubmatch(params, -1) 492 for _, p := range fields { 493 if strings.HasPrefix(p[1], "const TapAPI") { // 在struct 前加 ITapTrade:: 494 p[1] = fmt.Sprintf("const ITapTrade::%s", strings.ReplaceAll(p[1], "const ", "")) 495 } else if strings.HasPrefix(p[1], "TAP") { // 参数前加 ITapTrade 496 p[1] = "ITapTrade::" + p[1] 497 } 498 fn.Params = append(fn.Params, struct { 499 Type string 500 Name string 501 }{ 502 Type: p[1], 503 Name: p[2], 504 }) 505 } 506 if strings.HasPrefix(funcName, "On") { 507 onFuncs = append(onFuncs, fn) 508 } 509 } 510 511 fmt.Println("响应函数数量: ", len(onFuncs)) 512 513 // 取请求函数列表 514 for _, m := range matchs { 515 funcName := m[1] 516 // 只处理 非 On 开头 517 if strings.HasPrefix(funcName, "On") { 518 continue 519 } 520 params := m[2] 521 fn := Func{ 522 FuncName: funcName, 523 } 524 // virtual ITapTrade::TAPIINT32 TAP_CDECL VerificateUnFreezeInfo(TAPIUINT32 *sessionID, const TapAPIVerifyIdentityReq *qryReq) = 0; 525 // virtual ITapTrade::TAPIINT32 TAP_CDECL QryPositionSummary(ITapTrade::TAPIUINT32 *sessionID, const ITapTrade::TapAPIPositionQryReq *qryReq) = 0; 526 re = regexp.MustCompile(`((?:T|const T|I|const I)[\w:]+)\s+(\*?\s?\w+)`) 527 fields := re.FindAllStringSubmatch(params, -1) 528 for _, p := range fields { 529 fn.Params = append(fn.Params, struct { 530 Type string 531 Name string 532 }{ 533 // 去掉 参数中的 namespace 534 Type: strings.ReplaceAll(p[1], "ITapTrade::", ""), 535 Name: p[2], 536 }) 537 } 538 fnFuncs = append(fnFuncs, fn) 539 } 540 541 fmt.Println("请求函数数量: ", len(fnFuncs)) 542 return fnFuncs, onFuncs 543 } 544 545 // .h 文件中别名的 struct 转换为原始类型 546 var Rsp2ReqMv = map[string]string{ 547 "TapAPIFillLocalRemoveRsp": "TapAPIFillLocalRemoveReq", 548 "TapAPIFillLocalInputRsp": "TapAPIFillLocalInputReq", 549 "TapAPIOrderLocalTransferRsp": "TapAPIOrderLocalTransferReq", 550 "TapAPIOrderLocalModifyRsp": "TapAPIOrderLocalModifyReq", 551 "TapAPIOrderLocalInputRsp": "TapAPIOrderLocalInputReq", 552 "TapAPIOrderMarketDeleteRsp": "TapAPIOrderMarketDeleteReq", 553 "TapAPIOrderMarketInsertRsp": "TapAPIOrderMarketInsertReq", 554 "TapAPIHisOrderProcessQryRsp": "TapAPIHisOrderProcessQryReq", 555 "TapAPIOrderActivateReq": "TapAPIOrderCancelReq", 556 "TapAPIOrderDeactivateReq": "TapAPIOrderCancelReq", 557 "TapAPIOrderDeleteReq": "TapAPIOrderCancelReq", 558 } 559 560 // 调用函数,参数类型转换 561 var funcMapTradeFn = template.FuncMap{ 562 // 去掉变量前的 * 563 "trim": func(s string) string { return strings.Trim(s, "*") }, 564 // 在 trade_lnx.go 中的 C 头使用 565 // C++的自定义类型,还原为 C++ 原始类型 566 // 特别处理 ClientOrderNo -> char *, 正常处理会变成 char** 567 "CHeaderBaseType": func(typ, name string) string { 568 typ = strings.ReplaceAll(typ, "ITapTrade::", "") // On 函数类型中多出的前缀 569 typ = strings.ReplaceAll(typ, "const ", "") 570 if strings.HasPrefix(typ, "TapAPI") || strings.HasPrefix(typ, "const TapAPI") { // struct 571 // 重命名的 struct 572 if reqTpy, ok := Rsp2ReqMv[typ]; ok { 573 typ = reqTpy 574 } 575 return "struct " + typ 576 } 577 if strings.HasPrefix(typ, "TAPISTR_") || strings.HasPrefix(typ, "TAPSTR_") { 578 // 特别处理, 原定义为 char** 579 if strings.Contains(name, "ClientOrderNo") || strings.Contains(name, "ClientBuyOrderNo") || strings.Contains(name, "ClientSellOrderNo") || strings.Contains(name, "clientorderno") { 580 return "char" 581 } 582 return "char *" 583 } 584 switch typ { 585 case "ITapTradeAPINotify", "ITapQuoteAPINotify": // spi 586 return "void " 587 case "TAPIRightIDType", "TAPIINT32": 588 return "int" 589 case "TAPIUINT32": 590 return "unsigned int" 591 case "TAPICHAR", "const TAPICHAR", "TAPIYNFLAG": 592 return "char" 593 case "TAPIUINT16": 594 return "unsigned short" 595 case "TAPIDATE": 596 return "char *" 597 default: 598 fmt.Println(typ) 599 return typ 600 } 601 }, 602 // go 请求函数参数 603 // 转换为 go 的类型 604 "C2Go": func(typ, name string) string { 605 typ = strings.ReplaceAll(typ, "ITapTrade::", "") // On 函数类型中多出的前缀 606 typ = strings.ReplaceAll(typ, "const", "") 607 typ = strings.TrimSpace(typ) 608 switch typ { 609 case "ITapTradeAPINotify": // spi 610 return strings.Trim(name, "*") + " unsafe.Pointer" 611 case "TAPICHAR": // char* -> string 612 return strings.Trim(name, "*") + " string" 613 } 614 // *TAPISTR_50 615 if strings.Contains(name, "*") { 616 if !strings.Contains(typ, "TAPISTR_") { // 双重指针,只传递一层, 可能有问题!!! 617 typ = "*" + typ 618 } 619 name = strings.Trim(name, "*") 620 } 621 // 重命名的 struct 622 if strings.Contains(typ, "*") { 623 if reqTpy, ok := Rsp2ReqMv[strings.Trim(typ, "*")]; ok { 624 typ = "*" + reqTpy 625 } 626 } 627 return name + " " + typ 628 }, 629 // go 请求函数中调用 C 函数, 参数需转为 C 类型, 作为 C 函数的参数 630 // TAPIUINT32 => C.int 631 "Go2C": func(typ, name string) string { 632 typ = strings.ReplaceAll(typ, "const ", "") 633 typ = strings.TrimSpace(typ) 634 name = strings.Trim(name, "*") 635 if strings.HasPrefix(typ, "TapAPI") { 636 // 重命名的 struct 637 if reqTpy, ok := Rsp2ReqMv[typ]; ok { 638 typ = reqTpy 639 } 640 return fmt.Sprintf("(*C.struct_%s)(unsafe.Pointer(%s))", typ, name) 641 } 642 // TAPISTR_10 -> [11]byte 643 if strings.HasPrefix(typ, "TAPISTR_") || strings.HasPrefix(typ, "TAPSTR_") { 644 // 转换后的 & 会变成 & 645 s := fmt.Sprintf("(*C.char)(unsafe.Pointer(&%s[0]))", name) 646 return s 647 } 648 switch typ { 649 case "TAPICHAR": 650 return fmt.Sprintf("C.CString(%s)", name) 651 case "TAPIUINT16": 652 return fmt.Sprintf("C.ushort(%s)", name) 653 case "TAPIUINT32": 654 return fmt.Sprintf("(*C.uint)(unsafe.Pointer(%s))", name) 655 case "TAPIRightIDType": // int 656 return fmt.Sprintf("C.int(%s)", name) 657 } 658 fmt.Println(typ, " ", name) 659 return name 660 }, 661 } 662 663 // 响应函数定义, 参数类型转换 664 var funcMapTradeOn = template.FuncMap{ 665 // 响应函数变量的定义 666 // OnConnected func(hsotAddr string) 667 "DefineVar": func(typ, name string) string { 668 typ = strings.ReplaceAll(typ, "ITapTrade::", "") 669 typ = strings.ReplaceAll(typ, "const", "") 670 typ = strings.TrimSpace(typ) 671 if strings.Contains(typ, "TAPISTR_") { 672 typ = "string" 673 } else if strings.Contains(name, "*") { // name 中有* 指针 674 name = strings.Trim(name, "*") 675 if reqTpy, ok := Rsp2ReqMv[typ]; ok { 676 typ = reqTpy 677 } 678 typ = "*" + typ 679 } else { 680 switch typ { 681 case "TAPIDATE": // 原定义为 [n]byte 682 typ = "string" 683 } 684 } 685 return name + " " + typ 686 }, 687 // 响应函数声明中的参数, 由 c 转换为 cgo 类型 688 "CCB": func(typ, name string) string { 689 typ = strings.ReplaceAll(typ, "ITapTrade::", "") // On 函数类型中多出的前缀 690 typ = strings.ReplaceAll(typ, "const ", "") 691 // 回调函数里的 struct 参数 692 if strings.Contains(typ, "TapAPI") { 693 // 重命名的 struct 694 if reqTpy, ok := Rsp2ReqMv[typ]; ok { 695 typ = reqTpy 696 } 697 typ = fmt.Sprintf("*C.struct_%s", strings.TrimSpace(strings.Trim(typ, "*"))) 698 } else if strings.Contains(typ, "TAPISTR_") { 699 typ = "*C.char" 700 } else { 701 switch typ { 702 case "TAPIYNFLAG": 703 typ = "C.char" 704 case "TAPIINT32": 705 typ = "C.int" 706 case "TAPIUINT32": 707 typ = "C.uint" 708 case "bool": 709 typ = "C._BOOL" 710 case "int": 711 typ = "C.int" 712 case "TAPIDATE": 713 typ = "*C.char" 714 } 715 } 716 name = strings.Trim(name, "*") 717 return name + " " + typ 718 }, 719 // C的函数参数转为go类型 720 "cgo": func(typ, name string) string { 721 typ = strings.ReplaceAll(typ, "ITapTrade::", "") 722 typ = strings.ReplaceAll(typ, "const", "") 723 typ = strings.TrimSpace(typ) 724 if strings.Contains(typ, "TAPISTR_") { 725 return fmt.Sprintf("GBK(%s)", name) 726 } else if strings.Contains(name, "*") { // name 中有* 指针 727 // (*TapAPITradeLoginRspInfo)(unsafe.Pointer(loginRspInfo)) 728 name = strings.Trim(name, "*") 729 // 类型替代 730 if reqTpy, ok := Rsp2ReqMv[typ]; ok { 731 typ = reqTpy 732 } 733 return fmt.Sprintf("(*%s)(unsafe.Pointer(%s))", typ, name) 734 } else { 735 switch typ { 736 case "TAPIDATE": 737 return fmt.Sprintf("GBK(%s)", name) 738 } 739 } 740 return fmt.Sprintf("%s(%s)", typ, name) 741 }, 742 } 743 744 // genStructCgoTrade 生成用于 Cgo 的struct(struct中的字段均用C的基础类型) 745 func genStructCgoTrade() { 746 structs := getStructsCTrade() 747 writeTmpl("struct.cgo.tpl", "../trade/struct_cgo.h", structs, template.FuncMap{ 748 "cgo": func(typ, name string) string { 749 if strings.HasPrefix(typ, "TAPISTR_") { 750 return fmt.Sprintf("char %s[%s]", name, typ[8:]) 751 } else if (strings.HasPrefix(typ, "TapAPI") || strings.HasPrefix(typ, "TAPI")) && strings.HasSuffix(typ, "Type") { // TapAPIApplyStatusType TAPIHedgeFlagType 752 typ = "char" 753 } else { 754 switch typ { 755 case "TapAPICommodity", "TapAPINewOrder", "TapAPIContract": // 本来就是 struct 756 typ = "struct " + typ 757 case "TAPICHAR", "TAPIYNFLAG", "TAPILOGLEVEL", "TAPIAccountState", "TAPIORDERACT": 758 typ = "char" 759 case "TAPIUINT32": 760 typ = "unsigned int" 761 case "TAPIINT32": 762 typ = "int" 763 case "TAPIQVOLUME": // uint64 764 typ = "unsigned long long" 765 case "TAPIQDIFF": // int64 766 typ = "long long" 767 case "TAPIREAL64", "TAPIQPRICE": 768 typ = "double" 769 case "TAPIDTSTAMP": 770 return fmt.Sprintf("char %s[24]", name) 771 case "TAPIAUTHCODE": 772 return fmt.Sprintf("char %s[513]", name) 773 case "TAPIMACTYPE": 774 return fmt.Sprintf("char %s[13]", name) 775 case "TAPIDATE": 776 return fmt.Sprintf("char %s[11]", name) 777 case "TAPIDATETIME": 778 return fmt.Sprintf("char %s[20]", name) 779 case "TAPICommodityType": 780 typ = "char" 781 default: 782 fmt.Println(typ) 783 } 784 } 785 return typ + " " + name 786 }, 787 }) 788 } 789 790 type Struct struct { 791 Name string 792 Fields []struct { 793 Name string 794 Type string 795 Comment string 796 } 797 } 798 799 // genStructGoTrade 生成 struct golang 800 func genStructGoTrade() { 801 structs := getStructsCTrade() 802 // 模板生成(New后的名字要用完整的文件名) 803 writeTmpl("struct.go.tpl", "../trade/structs.go", structs) 804 } 805 806 // getStructsCTrade 获取 C 的 struct 定义 807 func getStructsCTrade() []Struct { 808 // 读取文件内容 809 str := readFile("iTapAPICommDef.h", "iTapTradeAPIDataType.h") 810 811 re := regexp.MustCompile(`struct\s*(\w*)\s*{([^}]*)}`) // 分成struct的注释,名称,字段两部分 812 matchs := re.FindAllStringSubmatch(string(str), -1) 813 814 structs := make([]Struct, 0) 815 for _, m := range matchs { 816 s := Struct{ 817 Name: m[1], 818 } 819 // 转换字段 820 reField := regexp.MustCompile(`(\w+)\s+([^;]+);\s+/{0,3}(.*)`) // 左杠2个或没有的情况 821 for _, f := range reField.FindAllStringSubmatch(m[2], -1) { 822 s.Fields = append(s.Fields, struct { 823 Name string 824 Type string 825 Comment string 826 }{ 827 Name: f[2], 828 Type: f[1], 829 Comment: f[3], 830 }) 831 } 832 structs = append(structs, s) 833 } 834 fmt.Println("struct 数量: ", len(structs)) 835 return structs 836 } 837 838 type DataType struct { 839 CType string // C++ 类型 840 TypeName string 841 Comment string 842 Const []struct { 843 TypeName string 844 Name string 845 Value string 846 Comment string 847 } 848 } 849 850 // genDataTypeGoTrade 生成 go 的数据类型 851 func genDataTypeGoTrade() { 852 dataTypes := getDataTypeCTrade() 853 // 模板生成(New后的名字要用完整的文件名) 854 writeTmpl("datatype.go.tpl", "../trade/datatype.go", dataTypes, template.FuncMap{ 855 "typeTrans": func(src string) string { 856 switch src { 857 case "char": 858 return "string" 859 case "int": 860 return "int" 861 case "long", "long long": 862 return "int64" 863 case "double": 864 return "float64" 865 case "unsigned int": 866 return "uint" 867 case "unsigned long": 868 return "uint64" 869 case "unsigned short": 870 return "uint16" 871 case "unsigned char": 872 return "uint8" 873 } 874 return src 875 }, 876 }) 877 } 878 879 // getDataTypeCTrade 获取 C 中数据类型的定义 880 func getDataTypeCTrade() []DataType { 881 // 读取文件内容 882 str := readFile("iTapAPICommDef.h", "iTapTradeAPIDataType.h") 883 884 /*//! 看涨看跌标示 885 typedef TAPICHAR TAPICallOrPutFlagType;*/ 886 // => type TAPICallOrPutFlagType byte 887 //! 长度为10的字符串 888 // typedef char TAPISTR_10[11]; 889 // => type TAPISTR_10 [11]byte 890 re := regexp.MustCompile(`//!?\s*(.*)\n\s+typedef\s+(\w+\s?\w+)\s+([\w[]+)`) 891 defines := re.FindAllStringSubmatch(str, -1) 892 893 /* //! 买权 894 const TAPICallOrPutFlagType TAPI_CALLPUT_FLAG_CALL = 'C';*/ 895 // const TAPI_CALLPUT_FLAG_CALL TAPICallOrPutFlagType = 'C' 896 reConst := regexp.MustCompile(`//!\s+(.*)\n\s+const\s+(\w+)\s+(\w+)\s+=\s?\'(\w)\'`) 897 consts := reConst.FindAllStringSubmatch(str, -1) 898 899 dataTypes := make([]DataType, 0) 900 for _, def := range defines { 901 // typedef char TAPISTR_10[11]; 902 comment := def[1] 903 srcType := def[2] // c++ 类型 904 typeName := def[3] // TAPISTR_10[11 ** 没有右括号 905 if strings.Contains(typeName, "[") { // char[nn] 906 srcType = fmt.Sprintf("[%s]byte", strings.Split(typeName, "[")[1]) 907 typeName = strings.Split(typeName, "[")[0] 908 } 909 dt := DataType{ 910 CType: srcType, 911 TypeName: typeName, 912 Comment: comment, 913 } 914 for _, c := range consts { 915 comment := c[1] 916 constType := c[2] 917 constName := c[3] 918 constValue := c[4] 919 if strings.Contains(constType, typeName) { 920 dt.Const = append(dt.Const, struct { 921 TypeName string 922 Name string 923 Value string 924 Comment string 925 }{ 926 TypeName: typeName, 927 Name: constName, 928 Value: constValue, 929 Comment: comment, 930 }) 931 } 932 } 933 dataTypes = append(dataTypes, dt) 934 } 935 936 fmt.Println("数量: ", len(dataTypes)) 937 return dataTypes 938 }