nimbuscontrols / EIPScanner

Free implementation of EtherNet/IP in C++
https://eipscanner.readthedocs.io/en/latest/
MIT License
233 stars 93 forks source link

Can`t build with visual studio #45

Closed singlebear closed 3 years ago

singlebear commented 3 years ago

Is there any plan to support VS compilation?

jadamroth commented 3 years ago

A recent release (1.1.0) with pull request from @luntik2012 included builds with the mingw compiler, so a lot of the _WIN32 preprocessors are already included. Several people have reported successfully compiling.

We currently don't have plans to implement any other compilers, so this is a feature that will need to come from the community. However, I don't think this should be too much work given lutnik's contributions

luntik2012 commented 3 years ago

do you mean VS projects support or just microsoft compiler support?

Broekman commented 3 years ago

Hi all,

I generallyuse MinGW on Windows however just for the sake off tried to compile with MSVC. Aside from a few issues, I got it to compile properly. Using MSVC again did give me a good reminder of why I switched to MinGW/GCC long ago, what a mess. Anyhow, to get it working:

  1. In CipString.h, using the _length in toStdString() results in error C2131: expression did not evaluate to a constant. For all purposes sake changed _length to a constant value of 255 for now.
  2. In connection manager the use of "std::uniform_int_distribution dist(0, std::numeric_limits::max());" results in illegal operations because for whatever reason, MSVC has a "max" macro defined... #undef max resolved the issue for now.
  3. "devices.push_back(IdentityItem{.identityObject=identityObject, .socketAddress=socketAddr});" is not supported. For whatever reason, MSVC does not yet support designated initializers. Removed the designators and placed in correct order: "devices.push_back(IdentityItem{socketAddr, identityObject});". Also does not work with "/std:c++latest" enabled.
  4. Changed close(_sockedFd); to closesocket(_sockedFd);
  5. Moved #include into the Unix #ifdef

I will try to include some of these changes in: https://github.com/nimbuscontrols/EIPScanner/issues/46

lpereira98 commented 3 years ago

Hello, im having trouble trying to execute an example from this library using:

Using @Broekman suggestions i managed to successfully build the projects EIPScanner and EIPScannerS using Visual Studio 2019. Now im trying to execute explicit_messaging project to make a Hello World to this project. I've changed C/C++ > General > Adicional Include Directories to the correct one. I've also changed Linker > Input > EIPScanner.lib to EIPScannerS.lib because the project that generates the lib is called EIPSCannerS. Everything seems fine but i have linker problems when trying to build explicit_messaging (and any other example project).

Error   LNK2019 unresolved external symbol __imp_htons referenced in function "public: class eipScanner::utils::Buffer & __cdecl eipScanner::utils::Buffer::operator<<(class eipScanner::sockets::EndPoint)" (??6Buffer@utils@eipScanner@@QEAAAEAV012@VEndPoint@sockets@2@@Z)   explicit_messaging  D:\SDKs\EIPScanner\examples\EIPScannerS.lib(Buffer.obj) 1   
Error   LNK2001 unresolved external symbol __imp_htons  explicit_messaging  D:\SDKs\EIPScanner\examples\EIPScannerS.lib(EndPoint.obj)   1   
Error   LNK2019 unresolved external symbol __imp_inet_ntoa referenced in function "public: __cdecl eipScanner::sockets::EndPoint::EndPoint(struct sockaddr_in &)" (??0EndPoint@sockets@eipScanner@@QEAA@AEAUsockaddr_in@@@Z)    explicit_messaging  D:\SDKs\EIPScanner\examples\EIPScannerS.lib(EndPoint.obj)   1   
Error   LNK2019 unresolved external symbol __imp_inet_pton referenced in function "public: __cdecl eipScanner::sockets::EndPoint::EndPoint(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int)" (??0EndPoint@sockets@eipScanner@@QEAA@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@Z)   explicit_messaging  D:\SDKs\EIPScanner\examples\EIPScannerS.lib(EndPoint.obj)   1   
Error   LNK2019 unresolved external symbol __WSAFDIsSet referenced in function "public: static void __cdecl eipScanner::sockets::BaseSocket::select(class std::vector<class std::shared_ptr<class eipScanner::sockets::BaseSocket>,class std::allocator<class std::shared_ptr<class eipScanner::sockets::BaseSocket> > >,class std::chrono::duration<__int64,struct std::ratio<1,1000> >)" (?select@BaseSocket@sockets@eipScanner@@SAXV?$vector@V?$shared_ptr@VBaseSocket@sockets@eipScanner@@@std@@V?$allocator@V?$shared_ptr@VBaseSocket@sockets@eipScanner@@@std@@@2@@std@@V?$duration@_JU?$ratio@$00$0DOI@@std@@@chrono@5@@Z)   explicit_messaging  D:\SDKs\EIPScanner\examples\EIPScannerS.lib(BaseSocket.obj) 1   
Error   LNK2019 unresolved external symbol __imp_closesocket referenced in function "protected: void __cdecl eipScanner::sockets::BaseSocket::Close(void)" (?Close@BaseSocket@sockets@eipScanner@@IEAAXXZ)  explicit_messaging  D:\SDKs\EIPScanner\examples\EIPScannerS.lib(BaseSocket.obj) 1   
Error   LNK2019 unresolved external symbol __imp_select referenced in function "public: static void __cdecl eipScanner::sockets::BaseSocket::select(class std::vector<class std::shared_ptr<class eipScanner::sockets::BaseSocket>,class std::allocator<class std::shared_ptr<class eipScanner::sockets::BaseSocket> > >,class std::chrono::duration<__int64,struct std::ratio<1,1000> >)" (?select@BaseSocket@sockets@eipScanner@@SAXV?$vector@V?$shared_ptr@VBaseSocket@sockets@eipScanner@@@std@@V?$allocator@V?$shared_ptr@VBaseSocket@sockets@eipScanner@@@std@@@2@@std@@V?$duration@_JU?$ratio@$00$0DOI@@std@@@chrono@5@@Z)   explicit_messaging  D:\SDKs\EIPScanner\examples\EIPScannerS.lib(BaseSocket.obj) 1   
Error   LNK2001 unresolved external symbol __imp_select explicit_messaging  D:\SDKs\EIPScanner\examples\EIPScannerS.lib(TCPSocket.obj)  1   
Error   LNK2019 unresolved external symbol __imp_setsockopt referenced in function "public: void __cdecl eipScanner::sockets::BaseSocket::setRecvTimeout(class std::chrono::duration<__int64,struct std::ratio<1,1000> > const &)" (?setRecvTimeout@BaseSocket@sockets@eipScanner@@QEAAXAEBV?$duration@_JU?$ratio@$00$0DOI@@std@@@chrono@std@@@Z)   explicit_messaging  D:\SDKs\EIPScanner\examples\EIPScannerS.lib(BaseSocket.obj) 1   
Error   LNK2019 unresolved external symbol __imp_shutdown referenced in function "protected: void __cdecl eipScanner::sockets::BaseSocket::Shutdown(void)" (?Shutdown@BaseSocket@sockets@eipScanner@@IEAAXXZ)   explicit_messaging  D:\SDKs\EIPScanner\examples\EIPScannerS.lib(BaseSocket.obj) 1   
Error   LNK2019 unresolved external symbol __imp_WSAGetLastError referenced in function "public: static int __cdecl eipScanner::sockets::BaseSocket::getLastError(void)" (?getLastError@BaseSocket@sockets@eipScanner@@SAHXZ)   explicit_messaging  D:\SDKs\EIPScanner\examples\EIPScannerS.lib(BaseSocket.obj) 1   
Error   LNK2019 unresolved external symbol __imp_connect referenced in function "public: __cdecl eipScanner::sockets::TCPSocket::TCPSocket(class eipScanner::sockets::EndPoint,class std::chrono::duration<__int64,struct std::ratio<1,1000> >)" (??0TCPSocket@sockets@eipScanner@@QEAA@VEndPoint@12@V?$duration@_JU?$ratio@$00$0DOI@@std@@@chrono@std@@@Z) explicit_messaging  D:\SDKs\EIPScanner\examples\EIPScannerS.lib(TCPSocket.obj)  1   
Error   LNK2019 unresolved external symbol __imp_getsockopt referenced in function "public: __cdecl eipScanner::sockets::TCPSocket::TCPSocket(class eipScanner::sockets::EndPoint,class std::chrono::duration<__int64,struct std::ratio<1,1000> >)" (??0TCPSocket@sockets@eipScanner@@QEAA@VEndPoint@12@V?$duration@_JU?$ratio@$00$0DOI@@std@@@chrono@std@@@Z)  explicit_messaging  D:\SDKs\EIPScanner\examples\EIPScannerS.lib(TCPSocket.obj)  1   
Error   LNK2019 unresolved external symbol __imp_recv referenced in function "public: virtual class std::vector<unsigned char,class std::allocator<unsigned char> > __cdecl eipScanner::sockets::TCPSocket::Receive(unsigned __int64)const " (?Receive@TCPSocket@sockets@eipScanner@@UEBA?AV?$vector@EV?$allocator@E@std@@@std@@_K@Z)   explicit_messaging  D:\SDKs\EIPScanner\examples\EIPScannerS.lib(TCPSocket.obj)  1   
Error   LNK2019 unresolved external symbol __imp_send referenced in function "public: virtual void __cdecl eipScanner::sockets::TCPSocket::Send(class std::vector<unsigned char,class std::allocator<unsigned char> > const &)const " (?Send@TCPSocket@sockets@eipScanner@@UEBAXAEBV?$vector@EV?$allocator@E@std@@@std@@@Z) explicit_messaging  D:\SDKs\EIPScanner\examples\EIPScannerS.lib(TCPSocket.obj)  1   
Error   LNK2019 unresolved external symbol __imp_socket referenced in function "public: __cdecl eipScanner::sockets::TCPSocket::TCPSocket(class eipScanner::sockets::EndPoint,class std::chrono::duration<__int64,struct std::ratio<1,1000> >)" (??0TCPSocket@sockets@eipScanner@@QEAA@VEndPoint@12@V?$duration@_JU?$ratio@$00$0DOI@@std@@@chrono@std@@@Z)  explicit_messaging  D:\SDKs\EIPScanner\examples\EIPScannerS.lib(TCPSocket.obj)  1   

I feel like i've tried everything to get this working. Any clue about what's the problem ? Any help would be very appreciated!

Broekman commented 3 years ago

Hi @lpereira98,

I will try to run on MSVC maybe this evening however it looks like you didn't link ws2_32 in your project as all the winsock function are unresolved (i.e. you have to link both the EIPScanner library as built, and ws2_32).

jadamroth commented 3 years ago

I may be wrong, but these look like linker errors that are native to the windows api and not the library itself.

I don’t have the ability to test this myself, but I see some stackoverflows that could be promising

lpereira98 commented 3 years ago

Ohh that was it! Thanks @Broekman and @jadamroth !!

Broekman commented 3 years ago

Assigned this ticket to myself - I will add MSVC support to the library later this week and get the things mentioned above resolved in a nicer way. Shouldn't be too much effort. Let me know if you run into any other problems while testing @lpereira98, thanks.

lpereira98 commented 3 years ago

Now that i can debug this project, im trying to connect to OpENer. I'm using a scanner developed in C# called Ethernet IP Explorer and i can connect to it and see some objects: imagem

But, using project examples from this library, i can only get exceptions everywhere, can't even connect. The code from this library is very very intuitive and i love it. I've made some debug and i think it is something to do with windows. Im creating the connection like this: auto si = std::make_shared<SessionInfo>("192.168.1.87", 0xAF12, std::chrono::seconds(10));

And executing this line:

_sockedFd = socket(AF_INET, SOCK_STREAM, 0); from TCPSocket.cpp i can only get it returning -1 which throws an exception right after.

The error code from BaseSocket::getLastError() is:

WSANOTINITIALISED 10093 Successful WSAStartup not yet performed. Either the application has not called WSAStartup or WSAStartup failed. The application may be accessing a socket that the current active task does not own (that is, trying to share a socket between tasks), or WSACleanup has been called too many times.

Any clue? And btw, thanks for being so helpful!

Broekman commented 3 years ago

Hi @lpereira98,

Just to verify, as the WSANOTINITIALISED error code describes, did you start Winsock? This is something where the specific application/user should have control over as it may also be a dependency for other applications, hence it's not in the library:

E.g. copy from my application:

WSADATA wsa_data;
int winsock_start = WSAStartup(MAKEWORD(2, 2), &wsa_data);
if (winsock_start != 0)
{
  logger->critical("Failed to start WinSock - error code: ", winsock_start);
}

On application exit also call to exit cleanly:

WSACleanup();
lpereira98 commented 3 years ago

Hi @Broekman ,

I have no words to thank you, i would never find it ! Now it works like a charm! Thanks for the quick and right answer ! Also, since this is mandatory to have in windows, i suggest this to be added to the examples source code :)

Broekman commented 3 years ago

No problem, I already added it to the examples yesterday (still on a separate branch). Also added the linkage of ws2_w32 in the CMake file for the examples 👍

https://github.com/nimbuscontrols/EIPScanner/tree/issue-45-add-msvc-support