patterncppMinor
Fetching specific foreign exchange rates from fixer using curl and jsconcpp in C++
Viewed 0 times
fixercurljsconcppexchangeratesandforeignusingspecificfetching
Problem
I am trying to create my own algorithmic trading system using C++. I have searched the web for a nice tutorial for such systems and I didn't find any. Then I started to learn about
```
#include
#include
#include
#include
#include
//writing call back function for storing fetched values in memory
static size_t WriteCallback(void contents, size_t size, size_t nmemb, void userp)
{
((std::string)userp)->append((char)contents, size * nmemb);
return size * nmemb;
}
int main(void)
{
std::string readBuffer;
//global initiliation of curl before calling a function
curl_global_init( CURL_GLOBAL_ALL );
//creating session handle
CURL * myHandle;
// We’ll store the result of CURL’s webpage retrieval, for simple error checking.
CURLcode result;
// notice the lack of major error-checking, for brevity
myHandle = curl_easy_init ( ) ;
//after creating handle we ill start transfering webpage
//curl_easy_setopt is used to tell libcurl how to behave.
//By setting the appropriate options, the application can change libcurl's behavior.
//CURLOPT_URL provide the URL to use in the request. Pass in a pointer to the URL to work with.
//sample json output >> {"base":"EUR","date":"2016-07-22","rates":{"GBP":0.84108,"USD":1.1014}}
curl_easy_setopt(myHandle, CURLOPT_URL, "http://api.fixer.io/latest?symbols=USD,GBP");
/ send all data to this function /
curl_easy_setopt(myHandle, CURLOPT_WRITEFUNCTION, WriteCallba
curl and jsoncpp libraries and even documentation of those libraries are not made for a novice programmer like me. I mostly reused most of the code for creating this scraper especially WriteCallback function which I directly copy pasted from other C++ code without understanding it. I am sharing this whole code because someone else doesn't need to reinvent the wheel and can use this code as a template. Anyway this code is working properly (Ubuntu 14.04, CodeBlocks IDE, API: fixer.io) and any kind of suggestion or feedback is welcomed.```
#include
#include
#include
#include
#include
//writing call back function for storing fetched values in memory
static size_t WriteCallback(void contents, size_t size, size_t nmemb, void userp)
{
((std::string)userp)->append((char)contents, size * nmemb);
return size * nmemb;
}
int main(void)
{
std::string readBuffer;
//global initiliation of curl before calling a function
curl_global_init( CURL_GLOBAL_ALL );
//creating session handle
CURL * myHandle;
// We’ll store the result of CURL’s webpage retrieval, for simple error checking.
CURLcode result;
// notice the lack of major error-checking, for brevity
myHandle = curl_easy_init ( ) ;
//after creating handle we ill start transfering webpage
//curl_easy_setopt is used to tell libcurl how to behave.
//By setting the appropriate options, the application can change libcurl's behavior.
//CURLOPT_URL provide the URL to use in the request. Pass in a pointer to the URL to work with.
//sample json output >> {"base":"EUR","date":"2016-07-22","rates":{"GBP":0.84108,"USD":1.1014}}
curl_easy_setopt(myHandle, CURLOPT_URL, "http://api.fixer.io/latest?symbols=USD,GBP");
/ send all data to this function /
curl_easy_setopt(myHandle, CURLOPT_WRITEFUNCTION, WriteCallba
Solution
These are C headers
You should probably use the C++ version (I hope you are not using C-String anywhere).
Header include paths
This should probably be
Curl is a C library.
Therefore any callbacks should be C functions (not C++ functions). There is no guarantee in the standard thay they use the same ABI.
Should be:
Never use C-Casts
C casts are hard to spot (in general). But also using C++ casts you can mark dangerious casts by uisng the appropriate cast.
I would use
Always check error codes.
All the following return an error code. You should validate these functions worked by checking this error code.
Prefer
The difference is that
RAII
When you see this pattern. You should be thinking of using RAII. This will make sure your resources are cleaned up correctly in all situations (including when exceptions are thrown) are the function returns early (aka
#include
#include You should probably use the C++ version (I hope you are not using C-String anywhere).
#include
#include Header include paths
#include This should probably be
json/json.h and you should specify the location where jsoncpp is installed with compiler flags. Curl is a C library.
Therefore any callbacks should be C functions (not C++ functions). There is no guarantee in the standard thay they use the same ABI.
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)Should be:
extern "C" size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)Never use C-Casts
C casts are hard to spot (in general). But also using C++ casts you can mark dangerious casts by uisng the appropriate cast.
((std::string*)userp)->append((char*)contents, size * nmemb);I would use
reinterpret_cast<> here. So that it is easy to spot and you intuitively know that this is a dangerous operation.reinterpret_cast(userp)->append(static_cast(contents), size * nmemb);Always check error codes.
All the following return an error code. You should validate these functions worked by checking this error code.
curl_global_init( CURL_GLOBAL_ALL );
curl_easy_setopt(myHandle, CURLOPT_URL, "http://api.fixer.io/latest?symbols=USD,GBP");
curl_easy_setopt(myHandle, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(myHandle, CURLOPT_WRITEDATA, &readBuffer);Prefer
"\n" over std::endlstd::cout<<"\nSucess parsing json\n"<<std::endl;
std::cout << root<< std::endl;
std::cout <<"Base = "<< root["base"].asString() << std::endl;
std::cout <<"Date = "<< root["date"].asString() << std::endl;
std::cout <<"Rate GBP ="<< root["rates"]["GBP"].asFloat() << std::endl;
std::cout <<"Rate USD ="<< root["rates"]["USD"].asFloat() << std::endl;The difference is that
std::endl also calls std::flush on the stream. There is no need to flush the stream manually. The stream is designed to flush when it needs too. When you do it manually you will make your code much more eneficent. RAII
myHandle = curl_easy_init ( ) ;
// STUFF
curl_easy_cleanup( myHandle );When you see this pattern. You should be thinking of using RAII. This will make sure your resources are cleaned up correctly in all situations (including when exceptions are thrown) are the function returns early (aka
return 1;).Code Snippets
#include <string.h>
#include <stdio.h>#include <strings>
#include <cstdio>#include <jsoncpp/json/json.h>static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)extern "C" size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)Context
StackExchange Code Review Q#135667, answer score: 2
Revisions (0)
No revisions yet.