Jerome
Jerome

Reputation: 874

Compiling bfx-cpp-api - Byte datatype undeclared

So I am looking to compile this project https://github.com/MMquant/bfx-cpp-api using the example code. I have included the cryptopp file that was suggested in the read me. It is found here: https://github.com/weidai11/cryptopp.

I am using Ubutnu version 17.10 and the GNU compiler.

Here's how I am compiling:

g++ example.cpp BitfinexAPI.cpp BitfinexAPI.hpp  -Icryptopp -I.  -o a -w -std=c++17

It seems strange that BitFinex would support broken code so I am fairly sure that the issue must be something that I am doing.

The errors I am getting are related to line 936 where the datatype 'byte' is not declared. My prediction is that I am missing a header file somewhere but any help would be appreciated.


$ g++ example.cpp BitfinexAPI.cpp BitfinexAPI.hpp  -Icryptopp -I.  -o a -w -std=c++17
BitfinexAPI.cpp: In static member function ‘static int BitfinexAPI::getBase64(const string&, std::__cxx11::string&)’:
BitfinexAPI.cpp:936:5: error: ‘byte’ was not declared in this scope
     byte buffer[1024] = {};
     ^~~~
BitfinexAPI.cpp:936:5: note: suggested alternative:
In file included from ../cryptopp/seckey.h:9:0,
                 from ../cryptopp/hmac.h:9,
                 from BitfinexAPI.cpp:37:
../cryptopp/config.h:222:23: note:   ‘CryptoPP::byte’
 typedef unsigned char byte;
                       ^~~~
BitfinexAPI.cpp:940:9: error: ‘buffer’ was not declared in this scope
         buffer[i] = content[i];
         ^~~~~~
BitfinexAPI.cpp:940:9: note: suggested alternative: ‘setbuffer’
         buffer[i] = content[i];
         ^~~~~~
         setbuffer
BitfinexAPI.cpp:943:21: error: ‘buffer’ was not declared in this scope
     StringSource ss(buffer, content.length(), true, new Base64Encoder( new StringSink(encoded), false));
                     ^~~~~~
BitfinexAPI.cpp:943:21: note: suggested alternative: ‘setbuffer’
     StringSource ss(buffer, content.length(), true, new Base64Encoder( new StringSink(encoded), false));
                     ^~~~~~
                     setbuffer
BitfinexAPI.cpp: In static member function ‘static int BitfinexAPI::getHmacSha384(const string&, const string&, std::__cxx11::string&)’:
BitfinexAPI.cpp:963:33: error: ISO C++ forbids declaration of ‘type name’ with no type [-fpermissive]
     SecByteBlock byteKey((const byte*)key.data(), key.size());
                                 ^~~~
BitfinexAPI.cpp:963:27: error: expected primary-expression before ‘const’
     SecByteBlock byteKey((const byte*)key.data(), key.size());
                           ^~~~~
BitfinexAPI.cpp:963:27: error: expected ‘)’ before ‘const’

Upvotes: 2

Views: 1067

Answers (2)

jww
jww

Reputation: 102386

Here's how I am compiling:

g++ example.cpp BitfinexAPI.cpp BitfinexAPI.hpp  -Icryptopp -I.  -o a -w -std=c++17

It seems strange that BitFinex would support broken code so I am fairly sure that the issue must be something that I am doing.

The errors I am getting are related to line 936 where the datatype 'byte' is not declared. My prediction is that I am missing a header file somewhere but any help would be appreciated.

@kabanus identified the problem.

Crypto++ used to provide a byte in the global C++ namespace. It was there for two reasons. First, it was a convenience item on Linux. You could use byte instead of CryptoPP::byte. Second, it avoided compiler errors on Windows. Microsoft SDK's provide a byte in the global namespace, and if we put a byte at CryptoPP::byte then compile errors resulted from ambiguous definitions.

C++17 came along and offered a std::byte; see P0298R0, A byte type definition. The global Crypto++ byte broke Linux when folks used a using namespace std. And it completely broke Microsoft because Microsoft SDK's provides a global byte. Ironically, the authors of P0298R0 work for Microsoft.

Crypto++ placing a byte in the global namespace was a C++ No-No. We got away with it for years, but it jumped up and bit us in C++17. We moved it into our namespace where it belongs. The check-in occurred at Commit 00f9818b5d8e, which happened after 5.6.5 was released and prior to 6.0 release.

Looking at the source for BitfinexAPI.cpp, this is probably the solution... open BitfinexAPI.cpp, and add the following at the top of the file:

// CRYPTOPP_NO_GLOBAL_BYTE signals byte is at CryptoPP::byte
#if defined(CRYPTOPP_NO_GLOBAL_BYTE)
  using CryptoPP::byte;
#endif

Also see std::byte on the Crypto++ wiki. We took the time to document it because of all the problems std::byte, Microsoft's global byte and our byte definitions are going to cause.


Related, you don't need to specify the C++ header on the command line. The compile error is due to the changes detailed above. All you need is:

g++ -std=c++17 example.cpp BitfinexAPI.cpp -I. ./cryptopp/libcryptopp.a -o example.exe

This assumes a directory structure of:

- bfx-api/
  |
  +- cryptopp/

The cryptopp/libcryptopp.a is a convenient way to sidestep those stupid Linux path problems that have existed for years. You link against the static archive which means you don't need a library at runtime.


Now open in the BFX issue tracker: Crypto++ byte change at Crypto++ 6.0. It should help the project engineer around the changes.

Upvotes: 2

kabanus
kabanus

Reputation: 25980

A bit tricky but I (think?) found it. byte is defined in the cryptopp code at:

https://github.com/weidai11/cryptopp/blob/master/config.h

line 222. So I'm guessing the config.h on your system is non-existent, probably because you didn't properly install the header. A common problem is having the library

sudo apt-get install libcrypto++

but missing the developer files (specifically the headers)

sudo apt-get install libcrypto++-dev

I'm not 100% about the package names (Debian user), should be close though.

Good catch from JTejedor:

Seems like the crypto guys placed a namespace around their definitions so as to not conflict with std::byte. You may want to add a CryptoPP:: to the byte definition in bfx (line 936), and if that works open a bug to the guys over there (or request a pull).

Upvotes: 2

Related Questions