Skip to content

Commit

Permalink
feat: add support for go binding
Browse files Browse the repository at this point in the history
  • Loading branch information
cryptochassis committed Aug 7, 2023
1 parent 6246a65 commit 9917bd8
Show file tree
Hide file tree
Showing 37 changed files with 783 additions and 59 deletions.
126 changes: 88 additions & 38 deletions binding/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,18 @@ else()
endforeach()
endif()

option(BUILD_PYTHON "Build Python Library" OFF)
message(STATUS "Build Python: ${BUILD_PYTHON}")

option(BUILD_JAVA "Build Java Library" OFF)
message(STATUS "Build Java: ${BUILD_JAVA}")

option(BUILD_CSHARP "Build C# Library" OFF)
message(STATUS "Build C#: ${BUILD_CSHARP}")

set(CMAKE_CXX_STANDARD 17)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()
get_filename_component(CCAPI_PROJECT_DIR ../ ABSOLUTE)
message(STATUS "CCAPI_PROJECT_DIR: ${CCAPI_PROJECT_DIR}")
find_package(OpenSSL REQUIRED)
message(STATUS "OPENSSL_INCLUDE_DIR: ${OPENSSL_INCLUDE_DIR}")
message(STATUS "OPENSSL_CRYPTO_LIBRARY: ${OPENSSL_CRYPTO_LIBRARY}")
get_filename_component(OPENSSL_CRYPTO_LIBRARY_DIR ${OPENSSL_CRYPTO_LIBRARY} DIRECTORY)
message(STATUS "OPENSSL_SSL_LIBRARY: ${OPENSSL_SSL_LIBRARY}")
get_filename_component(OPENSSL_SSL_LIBRARY_DIR ${OPENSSL_SSL_LIBRARY} DIRECTORY)
if(NOT CCAPI_LEGACY_USE_WEBSOCKETPP)
message(STATUS "use boost beast websocket")
if(NOT BOOST_INCLUDE_DIR)
Expand Down Expand Up @@ -145,12 +142,19 @@ else()
set(HFFIX_INCLUDE_DIR ${CCAPI_PROJECT_DIR}/dependency/hffix/include)
include_directories(${CCAPI_PROJECT_DIR}/include ${WEBSOCKETPP_INCLUDE_DIR} ${BOOST_INCLUDE_DIR} ${RAPIDJSON_INCLUDE_DIR} ${HFFIX_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR})
endif()
find_package(OpenSSL REQUIRED)

link_libraries(OpenSSL::Crypto OpenSSL::SSL)

find_package(ZLIB REQUIRED)
link_libraries(ZLIB::ZLIB)
message(STATUS "ZLIB_INCLUDE_DIRS: ${ZLIB_INCLUDE_DIRS}")
message(STATUS "ZLIB_LIBRARIES: ${ZLIB_LIBRARIES}")

set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(SOURCE_LOGGER ${CCAPI_PROJECT_DIR}/binding/ccapi_logger.cpp)
find_package(SWIG REQUIRED)
message(STATUS "SWIG_VERSION: ${SWIG_VERSION}")
message(STATUS "SWIG_EXECUTABLE: ${SWIG_EXECUTABLE}")
include(UseSWIG)
if(BUILD_TEST)
include(CTest)
Expand Down Expand Up @@ -217,33 +221,79 @@ add_compile_definitions(CCAPI_ENABLE_EXCHANGE_MEXC_FUTURES)

add_compile_definitions(CCAPI_ENABLE_EXCHANGE_WHITEBIT)

find_package(ZLIB REQUIRED)
link_libraries(ZLIB::ZLIB)
if(CCAPI_ENABLE_LOG_ERROR)
add_compile_definitions(CCAPI_ENABLE_LOG_ERROR)
endif()

if(BUILD_PYTHON)
configure_file(
swig_interface.i.in
${CMAKE_BINARY_DIR}/python/swig_interface.i
@ONLY)
set(SWIG_INTERFACE ${CMAKE_BINARY_DIR}/python/swig_interface.i)
add_subdirectory(python)
endif()

if(BUILD_JAVA)
configure_file(
swig_interface.i.in
${CMAKE_BINARY_DIR}/java/swig_interface.i
@ONLY)
set(SWIG_INTERFACE ${CMAKE_BINARY_DIR}/java/swig_interface.i)
add_subdirectory(java)
endif()

if(BUILD_CSHARP)
file(READ csharp/swig_interface_ccapi_language_specific.i SWIG_INTERFACE_CCAPI_LANGUAGE_SPECIFIC)
configure_file(
swig_interface.i.in
${CMAKE_BINARY_DIR}/csharp/swig_interface.i
@ONLY)
set(SWIG_INTERFACE ${CMAKE_BINARY_DIR}/csharp/swig_interface.i)
add_subdirectory(csharp)
if(CCAPI_ENABLE_LOG_WARN)
add_compile_definitions(CCAPI_ENABLE_LOG_WARN)
endif()

if(CCAPI_ENABLE_LOG_INFO)
add_compile_definitions(CCAPI_ENABLE_LOG_INFO)
endif()

if(CCAPI_ENABLE_LOG_DEBUG)
add_compile_definitions(CCAPI_ENABLE_LOG_DEBUG)
endif()

if(CCAPI_ENABLE_LOG_TRACE)
add_compile_definitions(CCAPI_ENABLE_LOG_TRACE)
endif()

set(LANG_LIST "python" "java" "csharp" "go" "javascript")
# option(BUILD_GO "Build ${LANG} library" OFF)
foreach(LANG IN LISTS LANG_LIST)
# message(STATUS "language is ${LANG}")
string(TOUPPER ${LANG} LANG_UPPER)
option(BUILD_${LANG_UPPER} "Build ${LANG} library" OFF)
message(STATUS "Build ${LANG_UPPER}: ${BUILD_${LANG_UPPER}}")
if(BUILD_${LANG_UPPER})
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${LANG}/swig_interface_ccapi_language_specific.i")
file(READ ${LANG}/swig_interface_ccapi_language_specific.i SWIG_INTERFACE_CCAPI_LANGUAGE_SPECIFIC)
endif()
configure_file(
swig_interface.i.in
${CMAKE_BINARY_DIR}/${LANG}/swig_interface.i
@ONLY)
set(SWIG_INTERFACE ${CMAKE_BINARY_DIR}/${LANG}/swig_interface.i)
add_subdirectory(${LANG})
endif()
endforeach()

# option(BUILD_PYTHON "Build Python Library" OFF)
# message(STATUS "Build Python: ${BUILD_PYTHON}")

# option(BUILD_JAVA "Build Java Library" OFF)
# message(STATUS "Build Java: ${BUILD_JAVA}")

# option(BUILD_CSHARP "Build C# Library" OFF)
# message(STATUS "Build C#: ${BUILD_CSHARP}")

# if(BUILD_PYTHON)
# configure_file(
# swig_interface.i.in
# ${CMAKE_BINARY_DIR}/python/swig_interface.i
# @ONLY)
# set(SWIG_INTERFACE ${CMAKE_BINARY_DIR}/python/swig_interface.i)
# add_subdirectory(python)
# endif()

# if(BUILD_JAVA)
# configure_file(
# swig_interface.i.in
# ${CMAKE_BINARY_DIR}/java/swig_interface.i
# @ONLY)
# set(SWIG_INTERFACE ${CMAKE_BINARY_DIR}/java/swig_interface.i)
# add_subdirectory(java)
# endif()

# if(BUILD_CSHARP)
# file(READ csharp/swig_interface_ccapi_language_specific.i SWIG_INTERFACE_CCAPI_LANGUAGE_SPECIFIC)
# configure_file(
# swig_interface.i.in
# ${CMAKE_BINARY_DIR}/csharp/swig_interface.i
# @ONLY)
# set(SWIG_INTERFACE ${CMAKE_BINARY_DIR}/csharp/swig_interface.i)
# add_subdirectory(csharp)
# endif()
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// usage: when generating the binding code, do cmake -DCCAPI_ENABLE_LOG_TRACE=ON ..., see https://github.com/crypto-chassis/ccapi#non-c
public class MainProgram {
class MyLogger : ccapi.Logger {
public override void LogMessage(string severity, string threadId, string timeISO, string fileName, string lineNumber, string message) {
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion binding/csharp/example/handle_exception/MainProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class MyEventHandler : ccapi.EventHandler {
throw new System.Exception("oops");
} catch (System.Exception e) {
System.Console.WriteLine(e.ToString());
System.Environment.Exit(0);
System.Environment.Exit(1);
}
return true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
class MainProgram {
class MyEventHandler : ccapi.EventHandler {
public override bool ProcessEvent(ccapi.Event event_, ccapi.Session session) {
if (event_.GetType_() == ccapi.Event.Type.SUBSCRIPTION_DATA) {
if (event_.GetType_() == ccapi.Event.Type.SUBSCRIPTION_STATUS) {
System.Console.WriteLine(string.Format("Received an event of type SUBSCRIPTION_STATUS:\n{0}", event_.ToStringPretty(2, 2)));
} else if (event_.GetType_() == ccapi.Event.Type.SUBSCRIPTION_DATA) {
foreach (var message in event_.GetMessageList()) {
System.Console.WriteLine(string.Format("Best bid and ask at {0} are:", message.GetTimeISO()));
foreach (var element in message.GetElementList()) {
Expand Down
131 changes: 131 additions & 0 deletions binding/go/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
set(NAME binding_${LANG})
project(${NAME})
set(SWIG_TARGET_NAME ccapi_${NAME})

# Find go cli
find_program(GO_EXECUTABLE NAMES go REQUIRED)
if(NOT GO_EXECUTABLE)
message(FATAL_ERROR "Check for go Program: not found")
else()
message(STATUS "Found go Program: ${GO_EXECUTABLE}")
endif()

execute_process(
COMMAND ${GO_EXECUTABLE} version
OUTPUT_VARIABLE GO_EXECUTABLE_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
message(STATUS "Go version: ${GO_EXECUTABLE_VERSION}")

set(GO_PACKAGE "ccapi")

# set_property(SOURCE ${SWIG_INTERFACE} PROPERTY CPLUSPLUS ON)
# set_property(SOURCE ${SWIG_INTERFACE} PROPERTY COMPILE_OPTIONS "-package;${GO_PACKAGE};-use-shlib")
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${SWIG_TARGET_NAME})
# set(SWIG_TARGET_NAME ${SWIG_TARGET_NAME})
add_custom_target(${SWIG_TARGET_NAME} ALL
COMMAND ${SWIG_EXECUTABLE} -outcurrentdir -c++ -go -package ${GO_PACKAGE} -I${CCAPI_PROJECT_DIR}/include ${SWIG_INTERFACE}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${SWIG_TARGET_NAME}
)
add_dependencies(${SWIG_TARGET_NAME} boost rapidjson hffix)


# swig_add_library(${SWIG_TARGET_NAME}
# LANGUAGE ${LANG}
# OUTPUT_DIR ${CMAKE_BINARY_DIR}/${LANG}/${SWIG_TARGET_NAME}
# SOURCES ${SWIG_INTERFACE})

# if(NOT CCAPI_LEGACY_USE_WEBSOCKETPP)
# add_dependencies(${SWIG_TARGET_NAME} boost rapidjson hffix)
# endif()
# set_property(TARGET ${SWIG_TARGET_NAME} PROPERTY SWIG_USE_TARGET_INCLUDE_DIRECTORIES ON)

set(PACKAGING_DIR packaging)
set(PACKAGING_DIR_FULL ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGING_DIR}/${BUILD_VERSION})
file(MAKE_DIRECTORY ${PACKAGING_DIR_FULL})
set(GO_PACKAGING_TARGET_NAME ${LANG}_${PACKAGING_DIR})

set(COMPILER_OPTIONS_FILE_PATH ${PACKAGING_DIR_FULL}/compiler_options.txt)
file(WRITE ${COMPILER_OPTIONS_FILE_PATH} "")
set(CGO_CXXFLAGS_LIST "")
list(APPEND CGO_CXXFLAGS_LIST -std=c++17 -fPIC -Wno-deprecated-declarations)
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
list(APPEND CGO_CXXFLAGS_LIST -g)
else()
list(APPEND CGO_CXXFLAGS_LIST -O3 -DNDEBUG)
endif()
list(APPEND CGO_CXXFLAGS_LIST -I${CCAPI_PROJECT_DIR}/include -I${BOOST_INCLUDE_DIR} -I${RAPIDJSON_INCLUDE_DIR} -I${HFFIX_INCLUDE_DIR} -I${OPENSSL_INCLUDE_DIR})
list(APPEND CGO_CXXFLAGS_LIST -DCCAPI_ENABLE_SERVICE_MARKET_DATA -DCCAPI_ENABLE_SERVICE_EXECUTION_MANAGEMENT -DCCAPI_ENABLE_SERVICE_FIX -DCCAPI_ENABLE_EXCHANGE_COINBASE -DCCAPI_ENABLE_EXCHANGE_GEMINI -DCCAPI_ENABLE_EXCHANGE_KRAKEN -DCCAPI_ENABLE_EXCHANGE_KRAKEN_FUTURES -DCCAPI_ENABLE_EXCHANGE_BITSTAMP -DCCAPI_ENABLE_EXCHANGE_BITFINEX -DCCAPI_ENABLE_EXCHANGE_BITMEX -DCCAPI_ENABLE_EXCHANGE_BINANCE_US -DCCAPI_ENABLE_EXCHANGE_BINANCE -DCCAPI_ENABLE_EXCHANGE_BINANCE_MARGIN -DCCAPI_ENABLE_EXCHANGE_BINANCE_USDS_FUTURES -DCCAPI_ENABLE_EXCHANGE_BINANCE_COIN_FUTURES -DCCAPI_ENABLE_EXCHANGE_HUOBI -DCCAPI_ENABLE_EXCHANGE_HUOBI_USDT_SWAP -DCCAPI_ENABLE_EXCHANGE_HUOBI_COIN_SWAP -DCCAPI_ENABLE_EXCHANGE_OKX -DCCAPI_ENABLE_EXCHANGE_ERISX -DCCAPI_ENABLE_EXCHANGE_KUCOIN -DCCAPI_ENABLE_EXCHANGE_KUCOIN_FUTURES -DCCAPI_ENABLE_EXCHANGE_DERIBIT -DCCAPI_ENABLE_EXCHANGE_GATEIO -DCCAPI_ENABLE_EXCHANGE_GATEIO_PERPETUAL_FUTURES -DCCAPI_ENABLE_EXCHANGE_CRYPTOCOM -DCCAPI_ENABLE_EXCHANGE_BYBIT -DCCAPI_ENABLE_EXCHANGE_BYBIT_DERIVATIVES -DCCAPI_ENABLE_EXCHANGE_ASCENDEX -DCCAPI_ENABLE_EXCHANGE_BITGET -DCCAPI_ENABLE_EXCHANGE_BITGET_FUTURES -DCCAPI_ENABLE_EXCHANGE_BITMART -DCCAPI_ENABLE_EXCHANGE_MEXC -DCCAPI_ENABLE_EXCHANGE_MEXC_FUTURES -DCCAPI_ENABLE_EXCHANGE_WHITEBIT)
if(CCAPI_ENABLE_LOG_ERROR)
list(APPEND CGO_CXXFLAGS_LIST -DCCAPI_ENABLE_LOG_ERROR)
endif()
if(CCAPI_ENABLE_LOG_WARN)
list(APPEND CGO_CXXFLAGS_LIST -DCCAPI_ENABLE_LOG_WARN)
endif()
if(CCAPI_ENABLE_LOG_INFO)
list(APPEND CGO_CXXFLAGS_LIST -DCCAPI_ENABLE_LOG_INFO)
endif()
if(CCAPI_ENABLE_LOG_DEBUG)
list(APPEND CGO_CXXFLAGS_LIST -DCCAPI_ENABLE_LOG_DEBUG)
endif()
if(CCAPI_ENABLE_LOG_TRACE)
list(APPEND CGO_CXXFLAGS_LIST -DCCAPI_ENABLE_LOG_TRACE)
endif()
list(JOIN CGO_CXXFLAGS_LIST " " CGO_CXXFLAGS)
message(STATUS "CGO_CXXFLAGS: ${CGO_CXXFLAGS}")
file(APPEND ${COMPILER_OPTIONS_FILE_PATH} "export CGO_CXXFLAGS='${CGO_CXXFLAGS}'\n\n")

set(CGO_LDFLAGS_LIST "")
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
list(APPEND CGO_LDFLAGS_LIST -g)
endif()
list(APPEND CGO_LDFLAGS_LIST -L${OPENSSL_CRYPTO_LIBRARY_DIR} -L${OPENSSL_SSL_LIBRARY_DIR} -lcrypto -lssl)
foreach(ZLIB_LIBRARY IN LISTS ZLIB_LIBRARIES)
get_filename_component(ZLIB_LIBRARY_DIR ${ZLIB_LIBRARY} DIRECTORY)
list(APPEND CGO_LDFLAGS_LIST -L${ZLIB_LIBRARY_DIR} -lz)
endforeach()
list(JOIN CGO_LDFLAGS_LIST " " CGO_LDFLAGS)
message(STATUS "CGO_LDFLAGS: ${CGO_LDFLAGS}")
file(APPEND ${COMPILER_OPTIONS_FILE_PATH} "export CGO_LDFLAGS='${CGO_LDFLAGS}'\n")

add_custom_target(${GO_PACKAGING_TARGET_NAME} ALL
# COMMAND ${GO_EXECUTABLE} -o ${PACKAGING_DIR_FULL} ${CMAKE_CURRENT_BINARY_DIR}/${SWIG_TARGET_NAME}/*.go
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/${SWIG_TARGET_NAME} ${PACKAGING_DIR_FULL}
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/go.mod ${PACKAGING_DIR_FULL}
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/ccapi_logger.cpp ${PACKAGING_DIR_FULL}
WORKING_DIRECTORY ${PACKAGING_DIR_FULL}
)
add_dependencies(${GO_PACKAGING_TARGET_NAME} ${SWIG_TARGET_NAME})

# # Test
# if(BUILD_TEST)
# # message(STATUS "BUILD_TEST")
# set(TEST_DIR ${CMAKE_CURRENT_BINARY_DIR}/test)
# file(COPY example DESTINATION ${TEST_DIR})
# set(SUBDIRECTORY_LIST "enable_library_logging" "execution_management_simple_request" "execution_management_simple_subscription" "fix_simple" "handle_exception" "market_data_multiple_subscription" "market_data_simple_request" "market_data_simple_subscription")
# foreach(SUBDIRECTORY IN LISTS SUBDIRECTORY_LIST)
# # message(STATUS "SUBDIRECTORY=${SUBDIRECTORY}")
# set(GO_TEST_TARGET_NAME go_test_${SUBDIRECTORY})
# set(GO_TEST_BUILD_DIRECTORY ${TEST_DIR}/example/${SUBDIRECTORY}/build)
# file(MAKE_DIRECTORY ${GO_TEST_BUILD_DIRECTORY})
# add_custom_target(${GO_TEST_TARGET_NAME} ALL
# COMMAND ${CMAKE_COMMAND} -E rm -rf *
# COMMAND ${Go_GOC_EXECUTABLE} -cp ${PACKAGING_DIR_FULL}/ccapi-${BUILD_VERSION}.jar -d . ../Main.go
# WORKING_DIRECTORY ${GO_TEST_BUILD_DIRECTORY}
# )
# add_dependencies(${GO_TEST_TARGET_NAME} ${GO_PACKAGING_TARGET_NAME})
# endforeach()
# file(COPY test DESTINATION ${TEST_DIR})
# set(GO_TEST_TARGET_NAME go_test_test)
# set(GO_TEST_BUILD_DIRECTORY ${TEST_DIR}/test/build)
# file(MAKE_DIRECTORY ${GO_TEST_BUILD_DIRECTORY})
# add_custom_target(${GO_TEST_TARGET_NAME} ALL
# COMMAND ${CMAKE_COMMAND} -E rm -rf *
# COMMAND ${Go_GOC_EXECUTABLE} -cp ${PACKAGING_DIR_FULL}/ccapi-${BUILD_VERSION}.jar -d . ../Main.go
# WORKING_DIRECTORY ${GO_TEST_BUILD_DIRECTORY}
# )
# add_dependencies(${GO_TEST_TARGET_NAME} ${GO_PACKAGING_TARGET_NAME})
# add_test(NAME go_test
# COMMAND ${Go_GO_EXECUTABLE} -cp ".:${PACKAGING_DIR_FULL}" -Dgo.library.path=${PACKAGING_DIR_FULL} Main
# WORKING_DIRECTORY ${GO_TEST_BUILD_DIRECTORY})
# endif()
7 changes: 7 additions & 0 deletions binding/go/example/enable_library_logging/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module main

require (
cryptochassis.com/ccapi v1.0.0
)

replace cryptochassis.com/ccapi => ../../../build/go/packaging/1.0.0
45 changes: 45 additions & 0 deletions binding/go/example/enable_library_logging/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// usage: when generating the binding code, do cmake -DCCAPI_ENABLE_LOG_TRACE=ON ..., see https://github.com/crypto-chassis/ccapi#non-c
package main

import (
"cryptochassis.com/ccapi"
"fmt"
"strings"
"sync"
"time"
)

type MyLogger struct {
ccapi.Logger
m sync.Mutex
}

func (ml *MyLogger) LogMessage(severity string, threadId string, timeISO string, fileName string, lineNumber string, message string) {
ml.m.Lock()
defer ml.m.Unlock()
fmt.Printf("%s: [%s] {%s:%s} %s%s%s\n", threadId, timeISO, fileName, lineNumber, severity, strings.Repeat(" ", 8), message)
}

func main() {
ml := &MyLogger{}
ml.Logger = ccapi.NewDirectorLogger(ml)
defer func() {
ccapi.DeleteDirectorLogger(ml.Logger)
}()
ccapi.SetLoggerLogger(ml)
option := ccapi.NewSessionOptions()
defer ccapi.DeleteSessionOptions(option)
config := ccapi.NewSessionConfigs()
defer ccapi.DeleteSessionConfigs(config)
session := ccapi.NewSession(option, config)
defer ccapi.DeleteSession(session)
subscriptionList := ccapi.NewSubscriptionList()
defer ccapi.DeleteSubscriptionList(subscriptionList)
subscription := ccapi.NewSubscription("okx", "BTC-USDT", "MARKET_DEPTH")
defer ccapi.DeleteSubscription(subscription)
subscriptionList.Add(subscription)
session.Subscribe(subscriptionList)
time.Sleep(10 * time.Second)
session.Stop()
fmt.Println("Bye")
}
7 changes: 7 additions & 0 deletions binding/go/example/execution_management_simple_request/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module main

require (
cryptochassis.com/ccapi v1.0.0
)

replace cryptochassis.com/ccapi => ../../../build/go/packaging/1.0.0

0 comments on commit 9917bd8

Please sign in to comment.