Skip to content

Commit c11eff4

Browse files
committed
Add compatibility with Windows
1 parent 4daad9b commit c11eff4

File tree

16 files changed

+318
-122
lines changed

16 files changed

+318
-122
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "3rdparty/pthread-win32"]
2+
path = 3rdparty/pthread-win32
3+
url = https://github.com/GerHobbelt/pthread-win32.git

3rdparty/endian/endian.h

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//
2+
// endian.h
3+
//
4+
// https://gist.github.com/panzi/6856583
5+
//
6+
// I, Mathias Panzenböck, place this file hereby into the public domain. Use
7+
// it at your own risk for whatever you like. In case there are
8+
// jurisdictions that don't support putting things in the public domain you
9+
// can also consider it to be "dual licensed" under the BSD, MIT and Apache
10+
// licenses, if you want to. This code is trivial anyway. Consider it an
11+
// example on how to get the endian conversion functions on different
12+
// platforms.
13+
14+
#ifndef PORTABLE_ENDIAN_H__
15+
#define PORTABLE_ENDIAN_H__
16+
17+
// Byte order
18+
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__CYGWIN__)
19+
# include <endian.h>
20+
#elif defined(__APPLE__)
21+
# include <libkern/OSByteOrder.h>
22+
23+
# define htobe16(x) OSSwapHostToBigInt16(x)
24+
# define htole16(x) OSSwapHostToLittleInt16(x)
25+
# define be16toh(x) OSSwapBigToHostInt16(x)
26+
# define le16toh(x) OSSwapLittleToHostInt16(x)
27+
28+
# define htobe32(x) OSSwapHostToBigInt32(x)
29+
# define htole32(x) OSSwapHostToLittleInt32(x)
30+
# define be32toh(x) OSSwapBigToHostInt32(x)
31+
# define le32toh(x) OSSwapLittleToHostInt32(x)
32+
33+
# define htobe64(x) OSSwapHostToBigInt64(x)
34+
# define htole64(x) OSSwapHostToLittleInt64(x)
35+
# define be64toh(x) OSSwapBigToHostInt64(x)
36+
# define le64toh(x) OSSwapLittleToHostInt64(x)
37+
38+
# define __BYTE_ORDER BYTE_ORDER
39+
# define __BIG_ENDIAN BIG_ENDIAN
40+
# define __LITTLE_ENDIAN LITTLE_ENDIAN
41+
# define __PDP_ENDIAN PDP_ENDIAN
42+
#elif defined(__OpenBSD__)
43+
# include <sys/endian.h>
44+
#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
45+
# include <sys/endian.h>
46+
47+
# define be16toh(x) betoh16(x)
48+
# define le16toh(x) letoh16(x)
49+
50+
# define be32toh(x) betoh32(x)
51+
# define le32toh(x) letoh32(x)
52+
53+
# define be64toh(x) betoh64(x)
54+
# define le64toh(x) letoh64(x)
55+
#elif defined(_WIN32)
56+
# include <stdlib.h>
57+
# if BYTE_ORDER == LITTLE_ENDIAN
58+
# if defined(_MSC_VER)
59+
# define htobe16(x) _byteswap_ushort(x)
60+
# define htole16(x) (x)
61+
# define be16toh(x) _byteswap_ushort(x)
62+
# define le16toh(x) (x)
63+
64+
# define htobe32(x) _byteswap_ulong(x)
65+
# define htole32(x) (x)
66+
# define be32toh(x) _byteswap_ulong(x)
67+
# define le32toh(x) (x)
68+
69+
# define htobe64(x) _byteswap_uint64(x)
70+
# define htole64(x) (x)
71+
# define be64toh(x) _byteswap_uint64(x)
72+
# define le64toh(x) (x)
73+
# elif defined(__GNUC__) || defined(__clang__)
74+
# define htobe16(x) __builtin_bswap16(x)
75+
# define htole16(x) (x)
76+
# define be16toh(x) __builtin_bswap16(x)
77+
# define le16toh(x) (x)
78+
79+
# define htobe32(x) __builtin_bswap32(x)
80+
# define htole32(x) (x)
81+
# define be32toh(x) __builtin_bswap32(x)
82+
# define le32toh(x) (x)
83+
84+
# define htobe64(x) __builtin_bswap64(x)
85+
# define htole64(x) (x)
86+
# define be64toh(x) __builtin_bswap64(x)
87+
# define le64toh(x) (x)
88+
# else
89+
# error Compiler is not supported
90+
# endif
91+
# else
92+
# error Byte order is not supported
93+
# endif
94+
95+
# define __BYTE_ORDER BYTE_ORDER
96+
# define __BIG_ENDIAN BIG_ENDIAN
97+
# define __LITTLE_ENDIAN LITTLE_ENDIAN
98+
# define __PDP_ENDIAN PDP_ENDIAN
99+
#else
100+
# error Platform is not supported
101+
#endif
102+
103+
#endif // PORTABLE_ENDIAN_H__

3rdparty/pthread-win32

Submodule pthread-win32 added at 3309f4d

CMakeLists.txt

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,19 @@ if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
99
endif()
1010

1111
option(WITH_ASAN "Compile with address sanitizer support" OFF)
12+
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
13+
14+
if(MSVC)
15+
set(BUILD_SHARED_LIBS OFF)
16+
endif()
1217

1318
##
1419
## Check C++11 support / enable global pedantic and Wall
1520
##
1621
include(DefineCXX17CompilerFlag)
1722
DEFINE_CXX_17_COMPILER_FLAG(CXX17_FLAG)
18-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic")
1923

20-
add_library(urcl SHARED
24+
add_library(urcl
2125
src/comm/tcp_socket.cpp
2226
src/comm/tcp_server.cpp
2327
src/control/reverse_interface.cpp
@@ -51,12 +55,24 @@ add_library(urcl SHARED
5155
src/helpers.cpp
5256
)
5357
add_library(ur_client_library::urcl ALIAS urcl)
54-
target_compile_options(urcl PRIVATE -Wall -Wextra -Wno-unused-parameter)
55-
target_compile_options(urcl PUBLIC ${CXX17_FLAG})
56-
if(WITH_ASAN)
57-
target_compile_options(urcl PUBLIC -fsanitize=address)
58-
target_link_options(urcl PUBLIC -fsanitize=address)
58+
59+
if(MSVC)
60+
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/endian)
61+
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/pthread-win32)
62+
target_link_libraries(urcl pthreadVCE3)
63+
target_link_libraries(urcl ws2_32)
64+
else()
65+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic")
66+
target_compile_options(urcl PRIVATE -Wall -Wextra -Wno-unused-parameter)
67+
68+
if(WITH_ASAN)
69+
target_compile_options(urcl PUBLIC -fsanitize=address)
70+
target_link_options(urcl PUBLIC -fsanitize=address)
71+
endif()
5972
endif()
73+
74+
target_compile_options(urcl PUBLIC ${CXX17_FLAG})
75+
6076
target_include_directories( urcl PUBLIC
6177
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
6278
$<INSTALL_INTERFACE:include>

CMakeModules/DefineCXX17CompilerFlag.cmake

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,26 @@ include(CheckCXXCompilerFlag)
3333
macro (DEFINE_CXX_17_COMPILER_FLAG _RESULT)
3434
if(NOT DEFINED "${_RESULT}")
3535

36-
if(NOT CMAKE_REQUIRED_QUIET)
37-
message(STATUS "Performing C++17 Test")
38-
endif()
39-
40-
# Check for default argument (all newer compilers)
41-
CHECK_CXX_COMPILER_FLAG("-std=c++17" COMPILER_SUPPORTS_CXX17)
42-
if(COMPILER_SUPPORTS_CXX17)
43-
set(${_RESULT} "-std=c++17" CACHE INTERNAL "C++17 flag")
36+
if(MSVC AND MSVC_VERSION GREATER 1919)
37+
set(${_RESULT} "/std:c++17" CACHE INTERNAL "C++17 flag")
4438
else()
45-
# Check for older version (before 2017)
46-
CHECK_CXX_COMPILER_FLAG("-std=c++1z" COMPILER_SUPPORTS_CXX1Z)
47-
if(COMPILER_SUPPORTS_CXX1Z)
48-
set(${_RESULT} "-std=c++1z" CACHE INTERNAL "C++17 flag")
39+
if(NOT CMAKE_REQUIRED_QUIET)
40+
message(STATUS "Performing C++17 Test")
41+
endif()
42+
43+
# Check for default argument (all newer compilers)
44+
CHECK_CXX_COMPILER_FLAG("-std=c++17" COMPILER_SUPPORTS_CXX17)
45+
if(COMPILER_SUPPORTS_CXX17)
46+
set(${_RESULT} "-std=c++17" CACHE INTERNAL "C++17 flag")
4947
else()
50-
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++17 support. Please use a different C++ compiler.")
48+
# Check for older version (before 2017)
49+
CHECK_CXX_COMPILER_FLAG("-std=c++1z" COMPILER_SUPPORTS_CXX1Z)
50+
if(COMPILER_SUPPORTS_CXX1Z)
51+
set(${_RESULT} "-std=c++1z" CACHE INTERNAL "C++17 flag")
52+
else()
53+
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++17 support. Please use a different C++ compiler.")
54+
endif()
5155
endif()
5256
endif()
53-
5457
endif()
5558
endmacro()

examples/dashboard_example.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@
3232

3333
#include <ur_client_library/log.h>
3434
#include <ur_client_library/ur/dashboard_client.h>
35+
#include <ur_client_library/comm/socket_t.h>
3536

3637
#include <iostream>
3738
#include <memory>
3839
#include <thread>
39-
#include <unistd.h>
4040

4141
using namespace urcl;
4242

@@ -97,7 +97,11 @@ int main(int argc, char* argv[])
9797
return 1;
9898
}
9999

100+
#ifdef _WIN32
101+
::Sleep(1000);
102+
#else // _WIN32
100103
sleep(1);
104+
#endif // _WIN32
101105

102106
// Play loaded program
103107
if (!my_dashboard->commandPlay())

include/ur_client_library/comm/pipeline.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ class Pipeline
342342
producer_.stopProducer();
343343
if (pThread_.joinable())
344344
{
345+
printf("Join Thread");
345346
pThread_.join();
346347
}
347348
if (cThread_.joinable())
@@ -396,13 +397,15 @@ class Pipeline
396397
std::vector<std::unique_ptr<T>> products;
397398
while (running_)
398399
{
400+
printf("runProducer() is running\n");
399401
if (!producer_.tryGet(products))
400402
{
401403
producer_.teardownProducer();
402404
running_ = false;
403405
break;
404406
}
405407

408+
printf("runProducer() for loop\n");
406409
for (auto& p : products)
407410
{
408411
if (!queue_.tryEnqueue(std::move(p)))
@@ -413,6 +416,7 @@ class Pipeline
413416

414417
products.clear();
415418
}
419+
printf("runProducer() ended\n");
416420
URCL_LOG_DEBUG("Pipeline producer ended! <%s>", name_.c_str());
417421
notifier_.stopped(name_);
418422
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2024, RoboDK Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#ifdef _WIN32
20+
21+
#define NOMINMAX
22+
#define WIN32_LEAN_AND_MEAN
23+
#include <WinSock2.h>
24+
#include <ws2tcpip.h>
25+
26+
#ifndef TCP_QUICKACK
27+
#define TCP_QUICKACK 12
28+
#endif
29+
30+
#ifdef ERROR
31+
#undef ERROR
32+
#endif // ERROR
33+
34+
typedef SOCKET socket_t;
35+
typedef SSIZE_T ssize_t;
36+
37+
static inline int ur_setsockopt(socket_t s, int level, int optname, const void* optval, unsigned int optlen)
38+
{
39+
return ::setsockopt(s, level, optname, reinterpret_cast<const char*>(optval), static_cast<int>(optlen));
40+
}
41+
42+
static inline int ur_close(socket_t s)
43+
{
44+
return ::closesocket(s);
45+
}
46+
47+
#else // _WIN32
48+
49+
#include <netdb.h>
50+
#include <sys/socket.h>
51+
#include <sys/types.h>
52+
#include <unistd.h>
53+
54+
typedef int socket_t;
55+
56+
#ifndef INVALID_SOCKET
57+
#define INVALID_SOCKET (-1)
58+
#endif
59+
60+
#define ur_setsockopt setsockopt
61+
#define ur_close close
62+
63+
#endif // _WIN32

include/ur_client_library/comm/stream.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@
1919
*/
2020

2121
#pragma once
22-
#include <netdb.h>
23-
#include <sys/socket.h>
24-
#include <sys/types.h>
2522
#include <atomic>
2623
#include <chrono>
2724
#include <mutex>

include/ur_client_library/comm/tcp_server.h

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,15 @@
2929
#ifndef UR_CLIENT_LIBRARY_TCP_SERVER_H_INCLUDED
3030
#define UR_CLIENT_LIBRARY_TCP_SERVER_H_INCLUDED
3131

32-
#include <netdb.h>
33-
#include <sys/socket.h>
34-
#include <sys/types.h>
35-
#include <unistd.h>
3632

3733
#include <atomic>
3834
#include <chrono>
3935
#include <functional>
4036
#include <thread>
4137

38+
#include "ur_client_library/comm/socket_t.h"
39+
40+
4241
namespace urcl
4342
{
4443
namespace comm
@@ -178,25 +177,22 @@ class TCPServer
178177
std::atomic<bool> keep_running_;
179178
std::thread worker_thread_;
180179

181-
std::atomic<int> listen_fd_;
180+
std::atomic<socket_t> listen_fd_;
182181
int port_;
183182

184-
int maxfd_;
183+
socket_t maxfd_;
185184
fd_set masterfds_;
186185
fd_set tempfds_;
187186

188187
uint32_t max_clients_allowed_;
189-
std::vector<int> client_fds_;
190-
191-
// Pipe for the self-pipe trick (https://cr.yp.to/docs/selfpipe.html)
192-
int self_pipe_[2];
188+
std::vector<socket_t> client_fds_;
193189

194190
static const int INPUT_BUFFER_SIZE = 100;
195191
char input_buffer_[INPUT_BUFFER_SIZE];
196192

197-
std::function<void(const int)> new_connection_callback_;
198-
std::function<void(const int)> disconnect_callback_;
199-
std::function<void(const int, char* buffer, int nbytesrecv)> message_callback_;
193+
std::function<void(const socket_t)> new_connection_callback_;
194+
std::function<void(const socket_t)> disconnect_callback_;
195+
std::function<void(const socket_t, char* buffer, int nbytesrecv)> message_callback_;
200196
};
201197

202198
} // namespace comm

0 commit comments

Comments
 (0)