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  }