Bill Kelly
2008-Sep-23 23:20 UTC
[Eventmachine-talk] building standalone EM library on windows
Greetings!
I''ve had the need to build EM as a standalone C library on
Windows. It took a bit more work this time than when I first
tried a standalone build back in early 2007.
As usual it''s all Bill Gates'' fault:
Short list of "Winsock Screw-Ups"
http://faculty.cs.wwu.edu/meehan/cs467/CS467s03/winsockdiffs.htm
Longer list of WinSock vs. BSD compatibility issues:
http://tangentsoft.net/wskfaq/articles/bsd-compatibility.html
But anyway. The reason EM currently is able to compile on
Windows is because ruby.h (via ruby''s win32/win32.h) provides
POSIX compatibility functions like open(), read(), write(),
close(), etc. (However, not all of these REALLY work with
sockets; see below...)
So once -D BUILD_FOR_RUBY is removed from the Makefile, and
ruby.h is no longer included, a few source files now fail to
compile.
My pragmatic but inelegant solution (diffs below) was just to
add #ifdef''s where needed, replacing calls to close() with
closesocket(), and replacing read() with recv(), etc. And I
simply disabled routines like evma_send_file_data_to_connection()
or KeyboardDescriptor::Read(), which didn''t look like they
would work properly on Windows whether they technically
compiled or not.
Probably a cleaner solution would have been for me to add
a win32_compat.cpp and win32_compat.h file which could be
included instead of ruby.h, and which would provide the
POSIX compatibility functions.
However, note that the read() supplied by ruby.h apparently
won''t work with sockets anyway. So I believe the
EventMachine_t::_ReadLoopBreaker() implementation using
read() on Windows will not function correctly, even though
it technically compiles under BUILD_FOR_RUBY. (I changed
it to call recv() on Windows, instead.)
Anyway - I''m not suggesting my patches below be applied
as-is. There''s probably a cleaner approach. But here''s
what I did in case it''s of use to anyone.
Regards,
Bill
M 791 kb.cpp
M 791 em.cpp
M 791 cmain.cpp
Status against revision: 791
Index: em.cpp
==================================================================--- em.cpp
(revision 791)
+++ em.cpp (working copy)
@@ -116,13 +116,22 @@
for (i = 0; i < Descriptors.size(); i++)
delete Descriptors[i];
+ #ifdef OS_WIN32
+ closesocket (LoopBreakerReader);
+ closesocket (LoopBreakerWriter);
+ #else
close (LoopBreakerReader);
close (LoopBreakerWriter);
+ #endif
+ #ifdef HAVE_EPOLL
if (epfd != -1)
close (epfd);
+ #endif
+ #ifdef HAVE_KQUEUE
if (kqfd != -1)
close (kqfd);
+ #endif
}
@@ -824,7 +833,11 @@
* and send a loop-break event back to user code.
*/
char buffer [1024];
+ #ifdef OS_WIN32
+ recv (LoopBreakerReader, buffer, sizeof(buffer), 0);
+ #else
read (LoopBreakerReader, buffer, sizeof(buffer));
+ #endif
if (EventCallback)
(*EventCallback)("", EM_LOOPBREAK_SIGNAL,
"", 0);
}
@@ -1669,6 +1682,13 @@
* or NULL if there was a problem.
*/
+ #ifdef OS_WIN32
+ throw std::runtime_error ("nonblocking OpenFileForWriting
unavailable on this platform");
+ #endif
+
+ // The whole rest of this function is only compiled on Unix systems.
+ #ifdef OS_UNIX
+
if (!filename || !*filename)
return NULL;
@@ -1679,7 +1699,8 @@
throw std::runtime_error ("no file-stream allocated");
Add (fsd);
return fsd->GetBinding().c_str();
-
+
+ #endif // OS_UNIX
}
Index: cmain.cpp
==================================================================--- cmain.cpp
(revision 791)
+++ cmain.cpp (working copy)
@@ -468,6 +468,8 @@
evma_send_file_data_to_connection
*********************************/
+#if defined(BUILD_FOR_RUBY) || !defined(OS_WIN32)
+
extern "C" int evma_send_file_data_to_connection (const char
*binding, const char *filename)
{
/* This is a sugaring over send_data_to_connection that reads a file
into a
@@ -528,3 +530,6 @@
return 0;
}
+#endif
+
+
Index: kb.cpp
==================================================================--- kb.cpp
(revision 791)
+++ kb.cpp (working copy)
@@ -75,10 +75,12 @@
void KeyboardDescriptor::Read()
{
+ #ifdef OS_UNIX
char c;
read (GetSocket(), &c, 1);
if (EventCallback)
(*EventCallback)(GetBinding().c_str(), EM_CONNECTION_READ,
&c, 1);
+ #endif
}
James Tucker
2008-Sep-24 04:30 UTC
[Eventmachine-talk] building standalone EM library on windows
Interesting observations. Thanks :) On 24 Sep 2008, at 07:20, Bill Kelly wrote:> Greetings! > > I''ve had the need to build EM as a standalone C library on > Windows. It took a bit more work this time than when I first > tried a standalone build back in early 2007. > > As usual it''s all Bill Gates'' fault: > > Short list of "Winsock Screw-Ups" > http://faculty.cs.wwu.edu/meehan/cs467/CS467s03/winsockdiffs.htm > > Longer list of WinSock vs. BSD compatibility issues: > http://tangentsoft.net/wskfaq/articles/bsd-compatibility.html > > > But anyway. The reason EM currently is able to compile on Windows > is because ruby.h (via ruby''s win32/win32.h) provides > POSIX compatibility functions like open(), read(), write(), > close(), etc. (However, not all of these REALLY work with > sockets; see below...) > > So once -D BUILD_FOR_RUBY is removed from the Makefile, and > ruby.h is no longer included, a few source files now fail to > compile. > > My pragmatic but inelegant solution (diffs below) was just to > add #ifdef''s where needed, replacing calls to close() with > closesocket(), and replacing read() with recv(), etc. And I > simply disabled routines like evma_send_file_data_to_connection() > or KeyboardDescriptor::Read(), which didn''t look like they > would work properly on Windows whether they technically > compiled or not. > > Probably a cleaner solution would have been for me to add > a win32_compat.cpp and win32_compat.h file which could be > included instead of ruby.h, and which would provide the POSIX > compatibility functions. > > However, note that the read() supplied by ruby.h apparently > won''t work with sockets anyway. So I believe the > EventMachine_t::_ReadLoopBreaker() implementation using > read() on Windows will not function correctly, even though > it technically compiles under BUILD_FOR_RUBY. (I changed > it to call recv() on Windows, instead.) > > > Anyway - I''m not suggesting my patches below be applied > as-is. There''s probably a cleaner approach. But here''s > what I did in case it''s of use to anyone. > > > Regards, > > Bill > > > M 791 kb.cpp > M 791 em.cpp > M 791 cmain.cpp > Status against revision: 791 > > > Index: em.cpp > ==================================================================> --- em.cpp (revision 791) > +++ em.cpp (working copy) > @@ -116,13 +116,22 @@ > for (i = 0; i < Descriptors.size(); i++) > delete Descriptors[i]; > > + #ifdef OS_WIN32 > + closesocket (LoopBreakerReader); > + closesocket (LoopBreakerWriter); > + #else > close (LoopBreakerReader); > close (LoopBreakerWriter); > + #endif > > + #ifdef HAVE_EPOLL > if (epfd != -1) > close (epfd); > + #endif > + #ifdef HAVE_KQUEUE > if (kqfd != -1) > close (kqfd); > + #endif > } > > > @@ -824,7 +833,11 @@ > * and send a loop-break event back to user code. > */ > char buffer [1024]; > + #ifdef OS_WIN32 > + recv (LoopBreakerReader, buffer, sizeof(buffer), 0); > + #else > read (LoopBreakerReader, buffer, sizeof(buffer)); > + #endif > if (EventCallback) > (*EventCallback)("", EM_LOOPBREAK_SIGNAL, "", 0); > } > @@ -1669,6 +1682,13 @@ > * or NULL if there was a problem. > */ > > + #ifdef OS_WIN32 > + throw std::runtime_error ("nonblocking OpenFileForWriting > unavailable on this platform"); > + #endif > + > + // The whole rest of this function is only compiled on Unix > systems. > + #ifdef OS_UNIX > + > if (!filename || !*filename) > return NULL; > > @@ -1679,7 +1699,8 @@ > throw std::runtime_error ("no file-stream allocated"); > Add (fsd); > return fsd->GetBinding().c_str(); > - > + > + #endif // OS_UNIX > } > > > Index: cmain.cpp > ==================================================================> --- cmain.cpp (revision 791) > +++ cmain.cpp (working copy) > @@ -468,6 +468,8 @@ > evma_send_file_data_to_connection > *********************************/ > > +#if defined(BUILD_FOR_RUBY) || !defined(OS_WIN32) > + > extern "C" int evma_send_file_data_to_connection (const char > *binding, const char *filename) > { > /* This is a sugaring over send_data_to_connection that reads > a file into a > @@ -528,3 +530,6 @@ > return 0; > } > > +#endif > + > + > Index: kb.cpp > ==================================================================> --- kb.cpp (revision 791) > +++ kb.cpp (working copy) > @@ -75,10 +75,12 @@ > > void KeyboardDescriptor::Read() > { > + #ifdef OS_UNIX > char c; > read (GetSocket(), &c, 1); > if (EventCallback) > (*EventCallback)(GetBinding().c_str(), > EM_CONNECTION_READ, &c, 1); > + #endif > } > > > _______________________________________________ > Eventmachine-talk mailing list > Eventmachine-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/eventmachine-talk