Add initial C# support
GitOrigin-RevId: c0ece19b41ca8e348285df95f9b81b188d3e5835
This commit is contained in:
parent
9310e29ff4
commit
70ad2664bd
@ -2,6 +2,10 @@ cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
|
||||
|
||||
project(TDLib VERSION 1.1.3 LANGUAGES CXX C)
|
||||
|
||||
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsStore")
|
||||
set(UWP 1)
|
||||
endif()
|
||||
|
||||
option(TD_ENABLE_JNI "Use \"ON\" to enable JNI-compatible TDLib API.")
|
||||
|
||||
if (NOT DEFINED CMAKE_MODULE_PATH)
|
||||
@ -145,6 +149,11 @@ elseif (INTEL)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
if (CMAKE_CXX_FLAGS_DEBUG MATCHES "/RTC1")
|
||||
string(REPLACE "/RTC1" " " CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
endif()
|
||||
add_definitions(-D_SCL_SECURE_NO_WARNINGS)
|
||||
|
||||
add_definitions(-DNTDDI_VERSION=0x06020000 -DWINVER=0x0602 -D_WIN32_WINNT=0x0602 -DNOMINMAX -DUNICODE -D_UNICODE)
|
||||
endif()
|
||||
if (CYGWIN)
|
||||
@ -275,6 +284,12 @@ set(TL_C_SCHEME_SOURCE
|
||||
${TL_C_AUTO}
|
||||
)
|
||||
|
||||
set_source_files_properties(${TL_WINDOWS_AUTO} PROPERTIES GENERATED TRUE)
|
||||
set(TL_WINDOWS_SCHEME_SOURCE
|
||||
${TL_TD_WINDOWS_AUTO}
|
||||
td/tl/tl_win_object.h
|
||||
)
|
||||
|
||||
set(TDLIB_SOURCE
|
||||
td/mtproto/AuthData.cpp
|
||||
td/mtproto/crypto.cpp
|
||||
@ -583,6 +598,30 @@ if (TD_ENABLE_JNI AND NOT ANDROID) # jni is available by default on Android
|
||||
target_link_libraries(tdclient PUBLIC ${JAVA_JVM_LIBRARY})
|
||||
endif()
|
||||
|
||||
if (TD_ENABLE_DOTNET)
|
||||
add_library(TdWindows SHARED
|
||||
td/telegram/ClientWindows.cpp
|
||||
td/telegram/LogWindows.cpp
|
||||
${TL_WINDOWS_SCHEME_SOURCE}
|
||||
)
|
||||
target_link_libraries(TdWindows PRIVATE tdclient tdutils)
|
||||
target_include_directories(TdWindows PUBLIC
|
||||
$<BUILD_INTERFACE:${TL_TD_AUTO_INCLUDES}>
|
||||
)
|
||||
if (NOT CMAKE_CROSSCOMPILING)
|
||||
add_dependencies(TdWindows generate_td_windows_api)
|
||||
endif()
|
||||
if (UWP)
|
||||
set_target_properties(TdWindows PROPERTIES VS_WINRT_COMPONENT "true")
|
||||
target_compile_options(TdWindows PUBLIC "/ZW")
|
||||
else()
|
||||
set_target_properties(TdWindows PROPERTIES COMPILE_FLAGS "/GR /clr")
|
||||
target_compile_options(TdWindows PUBLIC "/EHa")
|
||||
endif()
|
||||
|
||||
target_compile_options(TdWindows PUBLIC "/bigobj")
|
||||
endif()
|
||||
|
||||
# tdc - TDLib interface in pure c.
|
||||
add_library(tdc STATIC ${TL_C_SCHEME_SOURCE} td/telegram/td_c_client.cpp td/telegram/td_c_client.h)
|
||||
target_include_directories(tdc PUBLIC
|
||||
|
@ -27,7 +27,8 @@ set(TL_TD_JSON_AUTO
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
set(TL_TD_API_TLO ${CMAKE_CURRENT_SOURCE_DIR}/scheme/td_api.tlo PARENT_SCOPE)
|
||||
set(TL_TD_API_TLO ${CMAKE_CURRENT_SOURCE_DIR}/scheme/td_api.tlo)
|
||||
set(TL_TD_API_TLO ${TL_TD_API_TLO} PARENT_SCOPE)
|
||||
|
||||
set(TL_C_AUTO
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/td_tdc_api.cpp
|
||||
@ -36,6 +37,12 @@ set(TL_C_AUTO
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
set(TL_TD_WINDOWS_AUTO
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/TdWindowsApi.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/TdWindowsApi.h
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
set(TL_GENERATE_COMMON_SOURCE
|
||||
generate_common.cpp
|
||||
|
||||
@ -76,6 +83,7 @@ set(TL_GENERATE_JSON_SOURCE
|
||||
tl_json_converter.h
|
||||
)
|
||||
|
||||
|
||||
if (NOT CMAKE_CROSSCOMPILING)
|
||||
find_program(PHP_EXECUTABLE php)
|
||||
|
||||
@ -89,8 +97,7 @@ if (NOT CMAKE_CROSSCOMPILING)
|
||||
target_link_libraries(generate_common PRIVATE tdtl)
|
||||
add_custom_target(tl_generate_common
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND ${GENERATE_COMMON_CMD}
|
||||
COMMENT "Generate common tl source files"
|
||||
COMMAND ${GENERATE_COMMON_CMD} COMMENT "Generate common tl source files"
|
||||
DEPENDS generate_common scheme/mtproto_api.tlo scheme/telegram_api.tlo scheme/secret_api.tlo scheme/td_api.tlo
|
||||
)
|
||||
if (TD_ENABLE_JNI)
|
||||
@ -123,4 +130,13 @@ if (NOT CMAKE_CROSSCOMPILING)
|
||||
install(FILES JavadocTlDocumentationGenerator.php TlDocumentationGenerator.php DESTINATION bin/td/generate)
|
||||
install(FILES scheme/td_api.tlo scheme/td_api.tl DESTINATION bin/td/generate/scheme)
|
||||
endif()
|
||||
|
||||
add_executable(generate_td_windows_api_exe generate_td_windows_api.cpp tl_writer_win.h)
|
||||
target_link_libraries(generate_td_windows_api_exe PRIVATE tdtl)
|
||||
add_custom_target(generate_td_windows_api
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND generate_td_windows_api_exe ${TL_TD_API_TLO}
|
||||
COMMENT "Generate tl-files"
|
||||
DEPENDS generate_td_windows_api_exe ${TL_TD_API_TLO}
|
||||
)
|
||||
endif()
|
||||
|
25
td/generate/generate_td_windows_api.cpp
Normal file
25
td/generate/generate_td_windows_api.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "td/tl/tl_config.h"
|
||||
#include "td/tl/tl_generate.h"
|
||||
|
||||
#include "tl_writer_win.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
td::tl::tl_config config_td = td::tl::read_tl_config_from_file(argv[1]);
|
||||
|
||||
td::tl::write_tl_to_file(config_td, "auto/td/telegram/TdWindowsApi.cpp",
|
||||
td::tl::TlWriterWinCommon("TdApi", false, "#include \"td/telegram/TdWindowsApi.h\"\n"));
|
||||
td::tl::write_tl_to_file(config_td, "auto/td/telegram/TdWindowsApi.h",
|
||||
td::tl::TlWriterWinCommon("TdApi", true, "#include \"td/telegram/td_api.h\"\n"));
|
||||
|
||||
return 0;
|
||||
}
|
549
td/generate/tl_writer_win.h
Normal file
549
td/generate/tl_writer_win.h
Normal file
@ -0,0 +1,549 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/tl/tl_writer.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace td {
|
||||
namespace tl {
|
||||
|
||||
class TlWriterWinCommon : public TL_writer {
|
||||
public:
|
||||
bool is_header_;
|
||||
std::string prefix_;
|
||||
TlWriterWinCommon(const std::string &name, bool is_header, const std::string &prefix = "")
|
||||
: TL_writer(name), is_header_(is_header), prefix_(prefix) {
|
||||
}
|
||||
int get_max_arity(void) const override {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool is_built_in_simple_type(const std::string &name) const override {
|
||||
return name == "Bool" || name == "Int32" || name == "Int53" || name == "Int64" || name == "Double" || name == "String" || name == "Bytes";
|
||||
}
|
||||
bool is_built_in_complex_type(const std::string &name) const override {
|
||||
return name == "Vector";
|
||||
}
|
||||
bool is_type_bare(const tl_type *t) const override {
|
||||
return t->simple_constructors <= 1 || (is_built_in_simple_type(t->name) && t->name != "Bool") ||
|
||||
is_built_in_complex_type(t->name);
|
||||
}
|
||||
|
||||
std::vector<std::string> get_parsers(void) const override {
|
||||
return {"FromUnmanaged"};
|
||||
}
|
||||
int get_parser_type(const tl_combinator *t, const std::string &name) const override {
|
||||
return 0;
|
||||
}
|
||||
Mode get_parser_mode(int type) const override {
|
||||
return All; // Server;
|
||||
}
|
||||
std::vector<std::string> get_storers(void) const override {
|
||||
return {"ToUnmanaged", "ToString"};
|
||||
}
|
||||
std::vector<std::string> get_additional_functions(void) const override {
|
||||
return {"ToUnmanaged", "FromUnmanaged"};
|
||||
}
|
||||
int get_storer_type(const tl_combinator *t, const std::string &name) const override {
|
||||
return name == "ToString";
|
||||
}
|
||||
Mode get_storer_mode(int type) const override {
|
||||
return type <= 1 ? All : Server;
|
||||
}
|
||||
|
||||
std::string gen_base_tl_class_name(void) const override {
|
||||
return "BaseObject";
|
||||
}
|
||||
std::string gen_base_type_class_name(int arity) const override {
|
||||
assert(arity == 0);
|
||||
return "Object";
|
||||
}
|
||||
std::string gen_base_function_class_name(void) const override {
|
||||
return "Function";
|
||||
}
|
||||
|
||||
static std::string to_camelCase(const std::string &name) {
|
||||
return to_cCamelCase(name, false);
|
||||
}
|
||||
static std::string to_CamelCase(const std::string &name) {
|
||||
return to_cCamelCase(name, true);
|
||||
}
|
||||
static std::string to_cCamelCase(const std::string &name, bool flag) {
|
||||
bool next_to_upper = flag;
|
||||
std::string result;
|
||||
for (int i = 0; i < (int)name.size(); i++) {
|
||||
if (!is_alnum(name[i])) {
|
||||
next_to_upper = true;
|
||||
continue;
|
||||
}
|
||||
if (next_to_upper) {
|
||||
result += (char)to_upper(name[i]);
|
||||
next_to_upper = false;
|
||||
} else {
|
||||
result += name[i];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string gen_native_field_name(std::string name) const {
|
||||
for (int i = 0; i < (int)name.size(); i++) {
|
||||
if (!is_alnum(name[i])) {
|
||||
name[i] = '_';
|
||||
}
|
||||
}
|
||||
assert(name.size() > 0);
|
||||
assert(name[name.size() - 1] != '_');
|
||||
return name + "_";
|
||||
}
|
||||
|
||||
std::string gen_native_class_name(std::string name) const {
|
||||
if (name == "Object") {
|
||||
assert(0);
|
||||
}
|
||||
if (name == "#") {
|
||||
return "int32_t";
|
||||
}
|
||||
for (int i = 0; i < (int)name.size(); i++) {
|
||||
if (!is_alnum(name[i])) {
|
||||
name[i] = '_';
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
std::string gen_class_name(std::string name) const override {
|
||||
if (name == "Object" || name == "#") {
|
||||
assert(0);
|
||||
}
|
||||
return to_CamelCase(name);
|
||||
}
|
||||
std::string gen_field_name(std::string name) const override {
|
||||
assert(name.size() > 0);
|
||||
assert(is_alnum(name.back()));
|
||||
return to_CamelCase(name);
|
||||
}
|
||||
|
||||
std::string gen_type_name(const tl_tree_type *tree_type) const override {
|
||||
const tl_type *t = tree_type->type;
|
||||
const std::string &name = t->name;
|
||||
|
||||
if (name == "#") {
|
||||
assert(0);
|
||||
}
|
||||
if (name == "Bool") {
|
||||
return "bool";
|
||||
}
|
||||
if (name == "Int32") {
|
||||
return "int32";
|
||||
}
|
||||
if (name == "Int53" || name == "Int64") {
|
||||
return "int64";
|
||||
}
|
||||
if (name == "Double") {
|
||||
return "float64";
|
||||
}
|
||||
if (name == "String") {
|
||||
return "String^";
|
||||
}
|
||||
if (name == "Bytes") {
|
||||
return "Array<byte>^";
|
||||
}
|
||||
|
||||
if (name == "Vector") {
|
||||
assert(t->arity == 1);
|
||||
assert((int)tree_type->children.size() == 1);
|
||||
assert(tree_type->children[0]->get_type() == NODE_TYPE_TYPE);
|
||||
const tl_tree_type *child = static_cast<const tl_tree_type *>(tree_type->children[0]);
|
||||
|
||||
return "Array<" + gen_type_name(child) + ">^";
|
||||
}
|
||||
|
||||
assert(!is_built_in_simple_type(name) && !is_built_in_complex_type(name));
|
||||
|
||||
for (int i = 0; i < (int)tree_type->children.size(); i++) {
|
||||
assert(tree_type->children[i]->get_type() == NODE_TYPE_NAT_CONST);
|
||||
}
|
||||
|
||||
return gen_main_class_name(t) + "^";
|
||||
}
|
||||
std::string gen_output_begin(void) const override {
|
||||
return prefix_ +
|
||||
"#include \"td/utils/port/CxCli.h\"\n"
|
||||
"#include \"td/tl/tl_win_object.h\"\n\n"
|
||||
"namespace TdWindows {\n";
|
||||
}
|
||||
std::string gen_output_end() const override {
|
||||
return "}\n";
|
||||
}
|
||||
|
||||
std::string gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const override {
|
||||
if (!is_header_) {
|
||||
return "";
|
||||
}
|
||||
std::stringstream ss;
|
||||
ss << (is_proxy ? "interface" : "ref") << " class " << class_name << ";\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string gen_class_begin(const std::string &class_name, const std::string &base_class_name,
|
||||
bool is_proxy) const override {
|
||||
if (!is_header_) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "\npublic " << (is_proxy ? "interface" : "ref") << " class " << class_name << (is_proxy ? "" : " sealed")
|
||||
<< (class_name == gen_base_tl_class_name() ? "" : " : " + base_class_name) << " {\n"
|
||||
<< " public:\n";
|
||||
return ss.str();
|
||||
}
|
||||
std::string gen_class_end(void) const override {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string gen_field_definition(const std::string &class_name, const std::string &type_name,
|
||||
const std::string &field_name) const override {
|
||||
if (!is_header_) {
|
||||
return "";
|
||||
}
|
||||
auto fixed_field_name = field_name;
|
||||
if (field_name == class_name) {
|
||||
fixed_field_name += "Data";
|
||||
}
|
||||
if (type_name.substr(0, field_name.size()) == field_name) {
|
||||
auto fixed_type_name = "::TdWindows::" + type_name;
|
||||
std::stringstream ss;
|
||||
ss << "private:\n";
|
||||
ss << " " << fixed_type_name << " " << fixed_field_name << "Private;\n";
|
||||
ss << "public:\n";
|
||||
ss << " property " << fixed_type_name << " " << fixed_field_name << " {\n";
|
||||
ss << " " << fixed_type_name << " get() {\n";
|
||||
ss << " return " << fixed_field_name << "Private;\n";
|
||||
ss << " }\n";
|
||||
ss << " void set(" << fixed_type_name << " newValue) {\n";
|
||||
ss << " " << fixed_field_name << "Private = newValue;\n";
|
||||
ss << " }\n";
|
||||
ss << " }\n";
|
||||
return ss.str();
|
||||
}
|
||||
return " property " + type_name + " " + fixed_field_name + ";\n";
|
||||
}
|
||||
|
||||
std::string gen_store_function_begin(const std::string &storer_name, const std::string &class_name, int arity,
|
||||
std::vector<var_description> &vars, int storer_type) const override {
|
||||
if (storer_type < 0) {
|
||||
return "";
|
||||
}
|
||||
std::stringstream ss;
|
||||
ss << "\n";
|
||||
if (storer_type) {
|
||||
ss << (is_header_ ? " virtual " : "") << "String^ " << (is_header_ ? "" : gen_class_name(class_name) + "::")
|
||||
<< "ToString()" << (is_header_ ? " override;" : " {\n return ::TdWindows::ToString(this);\n}") << "\n";
|
||||
} else {
|
||||
ss << (is_header_ ? " virtual " : "") << "NativeObject^ "
|
||||
<< (is_header_ ? "" : gen_class_name(class_name) + "::") << "ToUnmanaged()";
|
||||
if (is_header_) {
|
||||
ss << ";\n";
|
||||
} else {
|
||||
ss << "{\n return REF_NEW NativeObject(::TdWindows::ToUnmanaged(this).release());\n}\n";
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
std::string gen_store_function_end(const std::vector<var_description> &vars, int storer_type) const override {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string gen_constructor_begin(int fields_num, const std::string &class_name, bool is_default) const override {
|
||||
std::stringstream ss;
|
||||
ss << "\n";
|
||||
ss << (is_header_ ? " " : gen_class_name(class_name) + "::") << gen_class_name(class_name) << "(";
|
||||
return ss.str();
|
||||
}
|
||||
std::string gen_constructor_parameter(int field_num, const std::string &class_name, const arg &a, bool is_default) const override {
|
||||
if (is_default) {
|
||||
return "";
|
||||
}
|
||||
std::stringstream ss;
|
||||
ss << (field_num == 0 ? "" : ", ");
|
||||
auto field_type = gen_field_type(a);
|
||||
if (field_type.substr(0, 5) == "Array") {
|
||||
ss << "CXCONST ";
|
||||
} else if (field_type.substr(0, 6) != "String" && to_upper(field_type[0]) == field_type[0]) {
|
||||
field_type = "::TdWindows::" + field_type;
|
||||
}
|
||||
ss << field_type << " " << to_camelCase(a.name);
|
||||
return ss.str();
|
||||
}
|
||||
std::string gen_constructor_field_init(int field_num, const std::string &class_name, const arg &a, bool is_default) const override {
|
||||
if (is_default || is_header_) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
if (field_num == 0) {
|
||||
ss << ") {\n";
|
||||
}
|
||||
auto field_name = gen_field_name(a.name);
|
||||
if (field_name == class_name) {
|
||||
field_name += "Data";
|
||||
}
|
||||
ss << " " << field_name << " = " << to_camelCase(a.name) << ";\n";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
std::string gen_constructor_end(const tl_combinator *t, int fields_num, bool is_default) const override {
|
||||
if (is_header_) {
|
||||
return ");\n";
|
||||
}
|
||||
std::stringstream ss;
|
||||
if (fields_num == 0) {
|
||||
ss << ") {\n";
|
||||
}
|
||||
ss << "}\n";
|
||||
return ss.str();
|
||||
}
|
||||
std::string gen_additional_function(const std::string &function_name, const tl_combinator *t,
|
||||
bool is_function) const override {
|
||||
std::stringstream ss;
|
||||
if (is_header_ && function_name == "ToUnmanaged") {
|
||||
ss << "};\n";
|
||||
}
|
||||
ss << "\n";
|
||||
if (function_name == "ToUnmanaged") {
|
||||
gen_to_unmanaged(ss, t);
|
||||
} else {
|
||||
gen_from_unmanaged(ss, t);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
void gen_to_unmanaged(std::stringstream &ss, const tl_combinator *t) const {
|
||||
auto native_class_name = gen_native_class_name(t->name);
|
||||
auto class_name = gen_class_name(t->name);
|
||||
ss << "td::td_api::object_ptr<td::td_api::" << native_class_name << "> ToUnmanaged(" << class_name
|
||||
<< "^ from)";
|
||||
if (is_header_) {
|
||||
ss << ";\n";
|
||||
return;
|
||||
}
|
||||
ss << "{\n"
|
||||
<< " if (!from) {\n"
|
||||
<< " return nullptr;\n"
|
||||
<< " }\n"
|
||||
<< " return td::td_api::make_object<td::td_api::" << native_class_name << ">(";
|
||||
bool is_first = true;
|
||||
for (auto &it : t->args) {
|
||||
if (is_first) {
|
||||
is_first = false;
|
||||
} else {
|
||||
ss << ", ";
|
||||
}
|
||||
auto field_name = gen_field_name(it.name);
|
||||
if (field_name == class_name) {
|
||||
field_name += "Data";
|
||||
}
|
||||
ss << "ToUnmanaged(from->" << field_name << ")";
|
||||
}
|
||||
ss << ");\n}\n";
|
||||
}
|
||||
|
||||
void gen_from_unmanaged(std::stringstream &ss, const tl_combinator *t) const {
|
||||
auto native_class_name = gen_native_class_name(t->name);
|
||||
auto class_name = gen_class_name(t->name);
|
||||
ss << class_name << "^ FromUnmanaged(td::td_api::" << native_class_name << "& from)";
|
||||
if (is_header_) {
|
||||
ss << ";\n";
|
||||
return;
|
||||
}
|
||||
ss << "{\n"
|
||||
<< " return REF_NEW " << class_name << "(";
|
||||
bool is_first = true;
|
||||
for (auto &it : t->args) {
|
||||
if (is_first) {
|
||||
is_first = false;
|
||||
} else {
|
||||
ss << ", ";
|
||||
}
|
||||
ss << (gen_field_type(it) == "Array<byte>^" ? "Bytes" : "") << "FromUnmanaged(from." << gen_native_field_name(it.name) << ")";
|
||||
}
|
||||
ss << ");\n}\n";
|
||||
}
|
||||
|
||||
std::string gen_array_type_name(const tl_tree_array *arr, const std::string &field_name) const override {
|
||||
assert(0);
|
||||
return std::string();
|
||||
}
|
||||
std::string gen_var_type_name(void) const override {
|
||||
assert(0);
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string gen_int_const(const tl_tree *tree_c, const std::vector<var_description> &vars) const override {
|
||||
assert(0);
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string gen_var_name(const var_description &desc) const override {
|
||||
assert(0);
|
||||
return "";
|
||||
}
|
||||
std::string gen_parameter_name(int index) const override {
|
||||
assert(0);
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string gen_class_alias(const std::string &class_name, const std::string &alias_name) const override {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string gen_vars(const tl_combinator *t, const tl_tree_type *result_type,
|
||||
std::vector<var_description> &vars) const override {
|
||||
assert(vars.empty());
|
||||
return "";
|
||||
}
|
||||
std::string gen_function_vars(const tl_combinator *t, std::vector<var_description> &vars) const override {
|
||||
assert(vars.empty());
|
||||
return "";
|
||||
}
|
||||
std::string gen_uni(const tl_tree_type *result_type, std::vector<var_description> &vars,
|
||||
bool check_negative) const override {
|
||||
assert(result_type->children.empty());
|
||||
return "";
|
||||
}
|
||||
std::string gen_constructor_id_store(int32_t id, int storer_type) const override {
|
||||
return "";
|
||||
}
|
||||
std::string gen_field_fetch(int field_num, const arg &a, std::vector<var_description> &vars, bool flat,
|
||||
int parser_type) const override {
|
||||
return "";
|
||||
// std::stringstream ss;
|
||||
// ss << gen_field_name(a.name) << " = from_unmanaged(from->" <<
|
||||
// gen_native_field_name(a.name) << ");\n"; return ss.str();
|
||||
}
|
||||
std::string gen_field_store(const arg &a, std::vector<var_description> &vars, bool flat,
|
||||
int storer_type) const override {
|
||||
return "";
|
||||
// std::stringstream ss;
|
||||
// ss << "to_unmanaged(" << gen_field_name(a.name) << ")";
|
||||
// return ss.str();
|
||||
}
|
||||
std::string gen_type_fetch(const std::string &field_name, const tl_tree_type *tree_type,
|
||||
const std::vector<var_description> &vars, int parser_type) const override {
|
||||
assert(vars.empty());
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string gen_type_store(const std::string &field_name, const tl_tree_type *tree_type,
|
||||
const std::vector<var_description> &vars, int storer_type) const override {
|
||||
return "";
|
||||
}
|
||||
std::string gen_var_type_fetch(const arg &a) const override {
|
||||
assert(0);
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string gen_get_id(const std::string &class_name, int32_t id, bool is_proxy) const override {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string gen_function_result_type(const tl_tree *result) const override {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name, int arity,
|
||||
std::vector<var_description> &vars, int parser_type) const override {
|
||||
return "";
|
||||
}
|
||||
std::string gen_fetch_function_end(int field_num, const std::vector<var_description> &vars,
|
||||
int parser_type) const override {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string gen_fetch_function_result_begin(const std::string &parser_name, const std::string &class_name,
|
||||
const tl_tree *result) const override {
|
||||
return "";
|
||||
}
|
||||
std::string gen_fetch_function_result_end(void) const override {
|
||||
return "";
|
||||
}
|
||||
std::string gen_fetch_function_result_any_begin(const std::string &parser_name, const std::string &class_name,
|
||||
bool is_proxy) const override {
|
||||
return "";
|
||||
}
|
||||
std::string gen_fetch_function_result_any_end(bool is_proxy) const override {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string gen_fetch_switch_begin(void) const override {
|
||||
return "";
|
||||
}
|
||||
std::string gen_fetch_switch_case(const tl_combinator *t, int arity) const override {
|
||||
return "";
|
||||
}
|
||||
std::string gen_fetch_switch_end(void) const override {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string gen_additional_proxy_function_begin(const std::string &function_name, const tl_type *type,
|
||||
const std::string &name, int arity, bool is_function) const override {
|
||||
std::stringstream ss;
|
||||
if (is_header_ && function_name == "ToUnmanaged") {
|
||||
ss << "};\n";
|
||||
}
|
||||
if (type == nullptr) {
|
||||
return ss.str();
|
||||
}
|
||||
auto native_class_name = gen_native_class_name(type->name);
|
||||
auto class_name = gen_class_name(type->name);
|
||||
if (function_name == "ToUnmanaged") {
|
||||
ss << "td::td_api::object_ptr<td::td_api::" << native_class_name << "> ToUnmanaged(" << class_name
|
||||
<< "^ from)";
|
||||
if (is_header_) {
|
||||
ss << ";\n";
|
||||
return ss.str();
|
||||
}
|
||||
ss << "{\n"
|
||||
<< " if (!from) {\n"
|
||||
<< " return nullptr;\n"
|
||||
<< " }\n"
|
||||
<< " return td::td_api::move_object_as<td::td_api::" << native_class_name << ">(from->ToUnmanaged()->get_object_ptr());\n}\n";
|
||||
} else {
|
||||
ss << class_name << "^ FromUnmanaged(td::td_api::" << native_class_name << "& from)";
|
||||
if (is_header_) {
|
||||
ss << ";\n";
|
||||
return ss.str();
|
||||
}
|
||||
ss << "{\n";
|
||||
ss << " CallFromUnmanaged<" << class_name << "^> res;\n";
|
||||
ss << " downcast_call(from, res);\n";
|
||||
ss << " return CallFromUnmanagedRes<" << class_name << "^>::res;\n";
|
||||
ss << "}\n";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
std::string gen_additional_proxy_function_case(const std::string &function_name, const tl_type *type,
|
||||
const std::string &class_name, int arity) const override {
|
||||
return "";
|
||||
}
|
||||
std::string gen_additional_proxy_function_case(const std::string &function_name, const tl_type *type,
|
||||
const tl_combinator *t, int arity, bool is_function) const override {
|
||||
return "";
|
||||
}
|
||||
std::string gen_additional_proxy_function_end(const std::string &function_name, const tl_type *type,
|
||||
bool is_function) const override {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace tl
|
||||
} // namespace td
|
95
td/telegram/ClientWindows.cpp
Normal file
95
td/telegram/ClientWindows.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "td/telegram/TdWindowsApi.h"
|
||||
|
||||
#include "td/telegram/Client.h"
|
||||
|
||||
#include "td/utils/port/CxCli.h"
|
||||
|
||||
namespace TdWindows {
|
||||
using namespace CxCli;
|
||||
|
||||
public interface class ClientResultHandler {
|
||||
void OnResult(BaseObject^ object);
|
||||
};
|
||||
|
||||
public ref class Client sealed {
|
||||
public:
|
||||
void Send(Function^ function, ClientResultHandler^ handler) {
|
||||
if (function == nullptr) {
|
||||
throw REF_NEW NullReferenceException("Function can't be null");
|
||||
}
|
||||
|
||||
std::uint64_t queryId = Increment(currentId);
|
||||
if (handler != nullptr) {
|
||||
handlers[queryId] = handler;
|
||||
}
|
||||
td::Client::Request request;
|
||||
request.id = queryId;
|
||||
request.function = td::td_api::move_object_as<td::td_api::Function>(ToUnmanaged(function)->get_object_ptr());
|
||||
client->send(std::move(request));
|
||||
}
|
||||
|
||||
BaseObject^ Execute(Function^ function) {
|
||||
if (function == nullptr) {
|
||||
throw REF_NEW NullReferenceException("Function can't be null");
|
||||
}
|
||||
|
||||
td::Client::Request request;
|
||||
request.id = 0;
|
||||
request.function = td::td_api::move_object_as<td::td_api::Function>(ToUnmanaged(function)->get_object_ptr());
|
||||
return FromUnmanaged(*client->execute(std::move(request)).object);
|
||||
}
|
||||
|
||||
void SetUpdatesHandler(ClientResultHandler^ handler) {
|
||||
handlers[0] = handler;
|
||||
}
|
||||
|
||||
void Run() {
|
||||
while (true) {
|
||||
auto response = client->receive(10.0);
|
||||
if (response.object != nullptr) {
|
||||
ProcessResult(response.id, FromUnmanaged(*response.object));
|
||||
|
||||
if (response.object->get_id() == td::td_api::updateAuthorizationState::ID &&
|
||||
static_cast<td::td_api::updateAuthorizationState &>(*response.object).authorization_state_->get_id() ==
|
||||
td::td_api::authorizationStateClosed::ID) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Client^ Create(ClientResultHandler^ updatesHandler) {
|
||||
return REF_NEW Client(updatesHandler);
|
||||
}
|
||||
|
||||
private:
|
||||
Client(ClientResultHandler^ updatesHandler) {
|
||||
client = new td::Client();
|
||||
handlers[0] = updatesHandler;
|
||||
}
|
||||
|
||||
~Client() {
|
||||
delete client;
|
||||
}
|
||||
|
||||
std::int64_t currentId = 0;
|
||||
ConcurrentDictionary<std::uint64_t, ClientResultHandler^> handlers;
|
||||
td::Client *client = nullptr;
|
||||
|
||||
void ProcessResult(std::uint64_t id, BaseObject^ object) {
|
||||
ClientResultHandler^ handler;
|
||||
// update handler stays forever
|
||||
if (id == 0 ? handlers.TryGetValue(id, handler) : handlers.TryRemove(id, handler)) {
|
||||
// TODO try/catch
|
||||
handler->OnResult(object);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace TdWindows
|
27
td/telegram/LogWindows.cpp
Normal file
27
td/telegram/LogWindows.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "td/telegram/Log.h"
|
||||
|
||||
#include "td/utils/port/CxCli.h"
|
||||
|
||||
namespace TdWindows {
|
||||
using namespace CxCli;
|
||||
public ref class Log sealed {
|
||||
public:
|
||||
static void SetFilePath(String^ filePath) {
|
||||
::td::Log::set_file_path(string_to_unmanaged(filePath));
|
||||
}
|
||||
|
||||
static void SetMaxFileSize(std::int64_t maxFileSize) {
|
||||
::td::Log::set_max_file_size(maxFileSize);
|
||||
}
|
||||
|
||||
static void SetVerbosityLevel(int verbosityLevel) {
|
||||
::td::Log::set_verbosity_level(verbosityLevel);
|
||||
}
|
||||
};
|
||||
} // namespace TdWindows
|
176
td/tl/tl_win_object.h
Normal file
176
td/tl/tl_win_object.h
Normal file
@ -0,0 +1,176 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/port/CxCli.h"
|
||||
#include "td/utils/tl_storers.h"
|
||||
|
||||
#include "td/telegram/td_api.h"
|
||||
#include "td/telegram/td_api.hpp"
|
||||
|
||||
namespace TdWindows {
|
||||
using namespace CxCli;
|
||||
|
||||
public ref class NativeObject sealed {
|
||||
public:
|
||||
virtual ~NativeObject() {
|
||||
if (data != nullptr) {
|
||||
get_object_ptr();
|
||||
}
|
||||
}
|
||||
internal:
|
||||
explicit NativeObject(td::td_api::BaseObject *fromData) {
|
||||
data = static_cast<void *>(fromData);
|
||||
}
|
||||
td::td_api::object_ptr<td::td_api::BaseObject> get_object_ptr() {
|
||||
auto res = static_cast<td::td_api::BaseObject *>(data);
|
||||
data = nullptr;
|
||||
return td::td_api::object_ptr<td::td_api::BaseObject>(res);
|
||||
}
|
||||
void *data;
|
||||
};
|
||||
|
||||
public interface class BaseObject {
|
||||
public:
|
||||
virtual NativeObject^ ToUnmanaged();
|
||||
};
|
||||
|
||||
//from unmanaged
|
||||
inline bool FromUnmanaged(bool val) {
|
||||
return val;
|
||||
}
|
||||
|
||||
inline int32 FromUnmanaged(int32 val) {
|
||||
return val;
|
||||
}
|
||||
|
||||
inline int64 FromUnmanaged(int64 val) {
|
||||
return val;
|
||||
}
|
||||
|
||||
inline float64 FromUnmanaged(float64 val) {
|
||||
return val;
|
||||
}
|
||||
|
||||
inline String^ FromUnmanaged(const std::string &from) {
|
||||
return string_from_unmanaged(from);
|
||||
}
|
||||
|
||||
inline auto CLRCALL BytesFromUnmanaged(const std::string &from) {
|
||||
Array<byte>^ res = REF_NEW Vector<byte>(td::narrow_cast<int>(from.size()));
|
||||
ArrayIndexType i = 0;
|
||||
for (auto b : from) {
|
||||
ArraySet(res, i++, b);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template <class FromT>
|
||||
auto CLRCALL FromUnmanaged(std::vector<FromT> &vec) {
|
||||
using ToT = decltype(FromUnmanaged(vec[0]));
|
||||
Array<ToT>^ res = REF_NEW Vector<ToT>(td::narrow_cast<int>(vec.size()));
|
||||
ArrayIndexType i = 0;
|
||||
for (auto &from : vec) {
|
||||
ArraySet(res, i++, FromUnmanaged(from));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
auto CLRCALL FromUnmanaged(td::td_api::object_ptr<T> &from) -> decltype(FromUnmanaged(*from.get())) {
|
||||
if (!from) {
|
||||
return nullptr;
|
||||
}
|
||||
return FromUnmanaged(*from.get());
|
||||
}
|
||||
|
||||
template <class ResT>
|
||||
ref class CallFromUnmanagedRes {
|
||||
public:
|
||||
static property ResT res;
|
||||
};
|
||||
|
||||
template <class ResT>
|
||||
struct CallFromUnmanaged {
|
||||
template <class T>
|
||||
void operator()(T &val) const {
|
||||
CallFromUnmanagedRes<ResT>::res = FromUnmanaged(val);
|
||||
}
|
||||
};
|
||||
|
||||
inline BaseObject^ FromUnmanaged(td::td_api::Function &from) {
|
||||
CallFromUnmanaged<BaseObject^> res;
|
||||
downcast_call(from, res);
|
||||
return CallFromUnmanagedRes<BaseObject^>::res;
|
||||
}
|
||||
|
||||
inline BaseObject^ FromUnmanaged(td::td_api::Object &from) {
|
||||
CallFromUnmanaged<BaseObject^> res;
|
||||
downcast_call(from, res);
|
||||
return CallFromUnmanagedRes<BaseObject^>::res;
|
||||
}
|
||||
|
||||
// to unmanaged
|
||||
inline bool ToUnmanaged(bool val) {
|
||||
return val;
|
||||
}
|
||||
inline int32 ToUnmanaged(int32 val) {
|
||||
return val;
|
||||
}
|
||||
|
||||
inline int64 ToUnmanaged(int64 val) {
|
||||
return val;
|
||||
}
|
||||
|
||||
inline float64 ToUnmanaged(float64 val) {
|
||||
return val;
|
||||
}
|
||||
|
||||
inline std::string ToUnmanaged(String ^from) {
|
||||
return string_to_unmanaged(from);
|
||||
}
|
||||
|
||||
inline std::string ToUnmanaged(Array<byte>^ from) {
|
||||
if (!from) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
ArrayIndexType size = ArraySize(from);
|
||||
std::string res(size, '\0');
|
||||
for (ArrayIndexType i = 0; i < size; i++) {
|
||||
res[i] = static_cast<char>(ArrayGet(from, i));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template <class FromT>
|
||||
auto ToUnmanaged(Array<FromT>^ from) {
|
||||
std::vector<decltype(ToUnmanaged(ArrayGet(from, 0)))> res;
|
||||
if (from && ArraySize(from)) {
|
||||
ArrayIndexType size = ArraySize(from);
|
||||
res.reserve(size);
|
||||
for (ArrayIndexType i = 0; i < size; i++) {
|
||||
res.push_back(ToUnmanaged(ArrayGet(from, i)));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
inline NativeObject^ ToUnmanaged(BaseObject^ from) {
|
||||
if (!from) {
|
||||
return REF_NEW NativeObject(nullptr);
|
||||
}
|
||||
|
||||
return from->ToUnmanaged();
|
||||
}
|
||||
|
||||
inline String^ ToString(BaseObject^ from) {
|
||||
return string_from_unmanaged(td::td_api::to_string(ToUnmanaged(from)->get_object_ptr()));
|
||||
}
|
||||
|
||||
} // namespace TdWindows
|
@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/port/config.h"
|
||||
#undef small
|
||||
|
||||
#if TD_WINRT
|
||||
|
Reference in New Issue
Block a user