diff --git a/vnpy/api/ctp/generator/generate_api_functions.py b/vnpy/api/ctp/generator/generate_api_functions.py index a0c66537..6d868a8f 100644 --- a/vnpy/api/ctp/generator/generate_api_functions.py +++ b/vnpy/api/ctp/generator/generate_api_functions.py @@ -1,6 +1,7 @@ """""" import importlib + class ApiGenerator: """API生成器""""" @@ -10,87 +11,87 @@ class ApiGenerator: self.prefix = prefix self.name = name self.class_name = class_name - + self.callbacks = {} self.functions = {} self.lines = {} - + self.structs = {} self.load_struct() - + def load_struct(self): """加载Struct""" module_name = f"{self.prefix}_struct" module = importlib.import_module(module_name) - + for name in dir(module): if "__" not in name: self.structs[name] = getattr(module, name) - + def run(self): """运行生成""" self.f_cpp = open(self.filename, "r") - + for line in self.f_cpp: self.process_line(line) - + self.f_cpp.close() - + self.generate_header_define() self.generate_header_process() self.generate_header_on() self.generate_header_function() - + self.generate_source_task() self.generate_source_switch() self.generate_source_process() self.generate_source_function() self.generate_source_on() self.generate_source_module() - + print("API生成成功") - + def process_line(self, line: str): """处理每行""" line = line.replace(";", "") line = line.replace("\n", "") line = line.replace("\t", "") line = line.replace("{}", "") - + if "virtual void On" in line: self.process_callback(line) elif "virtual int Req" in line: self.process_function(line) - def process_callback(self, line:str): + def process_callback(self, line: str): """处理回掉函数""" name = line[line.index("On"):line.index("(")] self.lines[name] = line - + d = self.generate_arg_dict(line) self.callbacks[name] = d - - def process_function(self, line:str): + + def process_function(self, line: str): """处理主动函数""" name = line[line.index("Req"):line.index("(")] - + d = self.generate_arg_dict(line) self.functions[name] = d - - def generate_arg_dict(self, line:str): + + def generate_arg_dict(self, line: str): """生成参数字典""" - args_str = line[line.index("(")+1:line.index(")")] + args_str = line[line.index("(") + 1:line.index(")")] if not args_str: return {} args = args_str.split(",") - + d = {} for arg in args: words = arg.split(" ") words = [word for word in words if word] d[words[1].replace("*", "")] = words[0] return d - + def generate_header_define(self): """""" filename = f"{self.prefix}_{self.name}_header_define.h" @@ -98,7 +99,7 @@ class ApiGenerator: for n, name in enumerate(self.callbacks.keys()): line = f"#define {name.upper()} {n}\n" f.write(line) - + def generate_header_process(self): """""" filename = f"{self.prefix}_{self.name}_header_process.h" @@ -106,31 +107,31 @@ class ApiGenerator: for name in self.callbacks.keys(): name = name.replace("On", "process") line = f"void {name}(Task *task);\n\n" - f.write(line) - + f.write(line) + def generate_header_on(self): """""" filename = f"{self.prefix}_{self.name}_header_on.h" with open(filename, "w") as f: for name, d in self.callbacks.items(): name = name.replace("On", "on") - - l = [] + + args_list = [] for type_ in d.values(): if type_ == "int": - l.append("int reqid") + args_list.append("int reqid") elif type_ == "bool": - l.append("bool last") + args_list.append("bool last") elif type_ == "CThostFtdcRspInfoField": - l.append("const dict &error") + args_list.append("const dict &error") else: - l.append("const dict &data") - - args_str = ", ".join(l) + args_list.append("const dict &data") + + args_str = ", ".join(args_list) line = f"virtual void {name}({args_str}) {{}};\n\n" - - f.write(line) - + + f.write(line) + def generate_header_function(self): """""" filename = f"{self.prefix}_{self.name}_header_function.h" @@ -138,20 +139,21 @@ class ApiGenerator: for name in self.functions.keys(): name = name.replace("Req", "req") line = f"int {name}(const dict &req, int reqid);\n\n" - f.write(line) - + f.write(line) + def generate_source_task(self): """""" filename = f"{self.prefix}_{self.name}_source_task.cpp" with open(filename, "w") as f: for name, d in self.callbacks.items(): line = self.lines[name] - - f.write(line.replace("virtual void ", f"void {self.class_name}::") + "\n") + + f.write(line.replace("virtual void ", + f"void {self.class_name}::") + "\n") f.write("{\n") f.write("\tTask task = Task();\n") f.write(f"\ttask.task_name = {name.upper()};\n") - + for field, type_ in d.items(): if type_ == "int": f.write(f"\ttask.task_id = {field};\n") @@ -163,7 +165,7 @@ class ApiGenerator: f.write(f"\t\t{type_} *task_error = new {type_}();\n") f.write(f"\t\t*task_error = *{field};\n") f.write(f"\t\ttask.task_error = task_error;\n") - f.write("\t}\n") + f.write("\t}\n") else: f.write(f"\tif ({field})\n") f.write("\t{\n") @@ -171,10 +173,10 @@ class ApiGenerator: f.write(f"\t\t*task_data = *{field};\n") f.write(f"\t\ttask.task_data = task_data;\n") f.write("\t}\n") - + f.write(f"\tthis->task_queue.push(task);\n") f.write("};\n\n") - + def generate_source_switch(self): """""" filename = f"{self.prefix}_{self.name}_source_switch.cpp" @@ -192,15 +194,16 @@ class ApiGenerator: filename = f"{self.prefix}_{self.name}_source_process.cpp" with open(filename, "w") as f: for name, d in self.callbacks.items(): - process_name = name.replace("On", "process") + process_name = name.replace("On", "process") on_name = name.replace("On", "on") - - f.write(f"void {self.class_name}::{process_name}(Task *task)\n") + + f.write( + f"void {self.class_name}::{process_name}(Task *task)\n") f.write("{\n") f.write("\tgil_scoped_acquire acquire;\n") - + args = [] - + for field, type_ in d.items(): if type_ == "int": args.append("task->task_id") @@ -208,44 +211,49 @@ class ApiGenerator: args.append("task->task_last") elif type_ == "CThostFtdcRspInfoField": args.append("error") - + f.write("\tdict error;\n") f.write("\tif (task->task_error)\n") f.write("\t{\n") - f.write(f"\t\t{type_} *task_error = ({type_}*)task->task_error;\n") - + f.write( + f"\t\t{type_} *task_error = ({type_}*)task->task_error;\n") + struct_fields = self.structs[type_] for struct_field, struct_type in struct_fields.items(): if struct_type == "string": - f.write(f"\t\terror[\"{struct_field}\"] = toUtf(task_error->{struct_field});\n") + f.write( + f"\t\terror[\"{struct_field}\"] = toUtf(task_error->{struct_field});\n") else: - f.write(f"\t\terror[\"{struct_field}\"] = task_error->{struct_field};\n") - + f.write( + f"\t\terror[\"{struct_field}\"] = task_error->{struct_field};\n") + f.write("\t\tdelete task->task_error;\n") f.write("\t}\n") else: args.append("data") - + f.write("\tdict data;\n") f.write("\tif (task->task_data)\n") f.write("\t{\n") - f.write(f"\t\t{type_} *task_data = ({type_}*)task->task_data;\n") - + f.write( + f"\t\t{type_} *task_data = ({type_}*)task->task_data;\n") + struct_fields = self.structs[type_] for struct_field, struct_type in struct_fields.items(): if struct_type == "string": - f.write(f"\t\tdata[\"{struct_field}\"] = toUtf(task_data->{struct_field});\n") + f.write( + f"\t\tdata[\"{struct_field}\"] = toUtf(task_data->{struct_field});\n") else: - f.write(f"\t\tdata[\"{struct_field}\"] = task_data->{struct_field};\n") - + f.write( + f"\t\tdata[\"{struct_field}\"] = task_data->{struct_field};\n") + f.write("\t\tdelete task->task_data;\n") - f.write("\t}\n") - - + f.write("\t}\n") + args_str = ", ".join(args) f.write(f"\tthis->{on_name}({args_str});\n") f.write("};\n\n") - + def generate_source_function(self): """""" filename = f"{self.prefix}_{self.name}_source_function.cpp" @@ -253,12 +261,13 @@ class ApiGenerator: for name, d in self.functions.items(): req_name = name.replace("Req", "req") type_ = list(d.values())[0] - - f.write(f"int {self.class_name}::{req_name}(const dict &req, int reqid)\n") + + f.write( + f"int {self.class_name}::{req_name}(const dict &req, int reqid)\n") f.write("{\n") f.write(f"\t{type_} myreq = {type_}();\n") f.write("\tmemset(&myreq, 0, sizeof(myreq));\n") - + struct_fields = self.structs[type_] for struct_field, struct_type in struct_fields.items(): if struct_type == "string": @@ -266,19 +275,18 @@ class ApiGenerator: else: line = f"\tget{struct_type.capitalize()}(req, \"{struct_field}\", &myreq.{struct_field});\n" f.write(line) - + f.write(f"\tint i = this->api->{name}(&myreq, reqid);\n") f.write("\treturn i;\n") f.write("};\n\n") - - + def generate_source_on(self): """""" filename = f"{self.prefix}_{self.name}_source_on.cpp" with open(filename, "w") as f: for name, d in self.callbacks.items(): on_name = name.replace("On", "on") - + args = [] bind_args = ["void", self.class_name, on_name] for field, type_ in d.items(): @@ -294,10 +302,10 @@ class ApiGenerator: else: args.append("const dict &data") bind_args.append("data") - + args_str = ", ".join(args) bind_args_str = ", ".join(bind_args) - + f.write(f"void {on_name}({args_str}) override\n") f.write("{\n") f.write("\ttry\n") @@ -307,10 +315,9 @@ class ApiGenerator: f.write("\tcatch (const error_already_set &e)\n") f.write("\t{\n") f.write(f"\t\tcout << e.what() << endl;\n") - f.write("\t}\n") + f.write("\t}\n") f.write("};\n\n") - - + def generate_source_module(self): """""" filename = f"{self.prefix}_{self.name}_source_module.cpp" @@ -318,15 +325,14 @@ class ApiGenerator: for name in self.functions.keys(): name = name.replace("Req", "req") f.write(f".def(\"{name}\", &{self.class_name}::{name})\n") - + f.write("\n") - + for name in self.callbacks.keys(): name = name.replace("On", "on") f.write(f".def(\"{name}\", &{self.class_name}::{name})\n") - + f.write(";\n") - if __name__ == "__main__": diff --git a/vnpy/api/ctp/generator/generate_data_type.py b/vnpy/api/ctp/generator/generate_data_type.py index 7a582a64..3ebd6543 100644 --- a/vnpy/api/ctp/generator/generate_data_type.py +++ b/vnpy/api/ctp/generator/generate_data_type.py @@ -7,6 +7,7 @@ TYPE_CPP2PY = { "short": "int", } + class DataTypeGenerator: """DataType生成器""" @@ -14,62 +15,62 @@ class DataTypeGenerator: """Constructor""" self.filename = filename self.prefix = prefix - + def run(self): """主函数""" self.f_cpp = open(self.filename, "r") self.f_define = open(f"{self.prefix}_constant.py", "w") self.f_typedef = open(f"{self.prefix}_typedef.py", "w") - + for line in self.f_cpp: self.process_line(line) - + self.f_cpp.close() self.f_define.close() self.f_typedef.close() - + print("DataType生成完毕") - + def process_line(self, line: str): """处理每行""" line = line.replace("\n", "") line = line.replace(";", "") - + if line.startswith("#define"): self.process_define(line) elif line.startswith("typedef"): self.process_typedef(line) - + def process_define(self, line: str): """处理常量定义""" words = line.split(" ") words = [word for word in words if word] if len(words) < 3: return - + name = words[1] value = words[2] - + new_line = f"{name} = {value}\n" self.f_define.write(new_line) - + def process_typedef(self, line: str): """处理类型定义""" words = line.split(" ") words = [word for word in words if word != " "] - + name = words[2] typedef = TYPE_CPP2PY[words[1]] - + if typedef == "char": if "[" in name: typedef = "string" name = name[:name.index("[")] - + new_line = f"{name} = \"{typedef}\"\n" self.f_typedef.write(new_line) if __name__ == "__main__": generator = DataTypeGenerator("ThostFtdcUserApiDataType.h", "ctp") - generator.run() \ No newline at end of file + generator.run() diff --git a/vnpy/api/ctp/generator/generate_struct.py b/vnpy/api/ctp/generator/generate_struct.py index 18a4b99d..f78844f2 100644 --- a/vnpy/api/ctp/generator/generate_struct.py +++ b/vnpy/api/ctp/generator/generate_struct.py @@ -1,6 +1,7 @@ """""" import importlib + class StructGenerator: """Struct生成器""" @@ -9,36 +10,36 @@ class StructGenerator: self.filename = filename self.prefix = prefix self.typedefs = {} - + self.load_constant() - + def load_constant(self): """""" module_name = f"{self.prefix}_typedef" module = importlib.import_module(module_name) - + for name in dir(module): if "__" not in name: self.typedefs[name] = getattr(module, name) - + def run(self): """运行生成""" self.f_cpp = open(self.filename, "r") self.f_struct = open(f"{self.prefix}_struct.py", "w") - + for line in self.f_cpp: self.process_line(line) - + self.f_cpp.close() self.f_struct.close() - + print("Struct生成成功") - + def process_line(self, line: str): """处理每行""" line = line.replace(";", "") line = line.replace("\n", "") - + if line.startswith("struct"): self.process_declare(line) elif line.startswith("{"): @@ -53,31 +54,31 @@ class StructGenerator: words = line.split(" ") name = words[1] end = "{" - + new_line = f"{name} = {end}\n" self.f_struct.write(new_line) - + def process_start(self, line: str): """处理开始""" pass - + def process_end(self, line: str): """处理结束""" new_line = "}\n\n" self.f_struct.write(new_line) - + def process_member(self, line: str): """处理成员""" words = line.split("\t") words = [word for word in words if word] - + py_type = self.typedefs[words[0]] name = words[1] - + new_line = f" \"{name}\": \"{py_type}\",\n" self.f_struct.write(new_line) if __name__ == "__main__": generator = StructGenerator("ThostFtdcUserApiStruct.h", "ctp") - generator.run() \ No newline at end of file + generator.run()