I am trying to test run the first example in curlpp and I am getting the error "Undefined symbol: _curl_easy_setopt". I have an idea that this is a problem with how I have tried linking the library. Below is my methodology.
header search paths -> for both debug and release -> (I typed) /usr/local/include
library search paths -> for both debug and release -> (I typed) /usr/local/lib
other linker flags -> for both debug and release -> (I typed) -lcurlpp
I ran the the example with an API url I have used in python successfully in place of "example.com".This is a picture of the full error. Thank you!`
#include <string>
#include <sstream>
#include <iostream>
#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
namespace
{
const long MyPort = 80;
}
/**
* This example is made to show you how you can use the Options.
*/
int main(int, char **)
{
try
{
curlpp::Cleanup myCleanup;
// First easy example.
{
// The first easiest example is to retreive the content of
// a web page and put it in a stream.
std::cout << curlpp::options::Url("https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=VSLR&frequency=5min&outputsize=full&datatype=json&apikey=IGDV8B3MO9GQ9R35");
// You don't need to use just the standard outputs. You
// can use any stream:
std::ostringstream os;
os << curlpp::options::Url("https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=VSLR&frequency=5min&outputsize=full&datatype=json&apikey=IGDV8B3MO9GQ9R35");
}
// More elaborate example.
{
// What the previous example done there was simply
// to create a curlpp::Easy class, which is the basic
// object in cURLpp, and then set the Url option.
// curlpp::options classes are the primitives that allow to specify
// values to the requests.
curlpp::options::Url myUrl(std::string("https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=VSLR&frequency=5min&outputsize=full&datatype=json&apikey=IGDV8B3MO9GQ9R35"));
curlpp::Easy myRequest;
myRequest.setOpt(myUrl);
// Now that all the options we wanted to set are there, we need to
// actually do the request. the "perform" method does actually that.
// With that call, the request will be done and the content of that URL
// will be printed in std::cout (which is the default).
myRequest.perform();
// If we wanted to put the content of the URL within a string stream
// (or any type of std::ostream, for that matter), like the first example,
// we would use the WriteStrem option like this:
std::ostringstream os;
curlpp::options::WriteStream ws(&os);
myRequest.setOpt(ws);
myRequest.perform();
// There is some shorcut within curlpp that allow you to write shorter code
// like this:
os << myRequest;
// That would do exactly what the previous code was doing.
}
// Creation of the URL option.
curlpp::options::Url myUrl(std::string("https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=VSLR&frequency=5min&outputsize=full&datatype=json&apikey=IGDV8B3MO9GQ9R35"));
// Copy construct from the other URL.
curlpp::options::Url myUrl2(myUrl);
// Creation of the port option.
curlpp::options::Port myPort(MyPort);
// Creation of the request.
curlpp::Easy myRequest;
// Creation of an option that contain a copy of the URL option.
curlpp::OptionBase *mytest = myUrl.clone();
myRequest.setOpt(*mytest);
// You can reuse the base option for other type of option
// and set the option to the request. but first, don't forget
// to delete the previous memory. You can delete it since the
// option is internally duplicated for the request.
delete mytest;
mytest = myPort.clone();
myRequest.setOpt(*mytest);
delete mytest;
// You can clone an option directly to the same type of
// option.
curlpp::options::Url *myUrl3 = myUrl.clone();
myRequest.setOpt(myUrl3);
// Now myUrl3 is owned by the request we will NOT use
// it anymore.
// You don't need to declare an option if you just want
// to use it once.
myRequest.setOpt(curlpp::options::Url("https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=VSLR&frequency=5min&outputsize=full&datatype=json&apikey=IGDV8B3MO9GQ9R35"));
// Note that the previous line wasn't really efficient
// because we create the option, this option is duplicated
// for the request and then the option destructor is called.
// You can use this instead:
myRequest.setOpt(new curlpp::options::Url("https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=VSLR&frequency=5min&outputsize=full&datatype=json&apikey=IGDV8B3MO9GQ9R35"));
// Note that with this the request will use directly this
// instance we just created. Be aware that if you pass an
// Option pointer to the setOpt function, it will consider
// the instance has its own instance. The Option instance
// will be deleted when the request will be deleted, so
// don't use the instance further in your code.
// Doing the previous line is efficient as this:
myRequest.setOpt(myUrl.clone());
// You can retreive the value of a specific option.
std::cout << myUrl2.getValue() << std::endl;
// Perform the transaction with the options set.
myRequest.perform();
}
catch( curlpp::RuntimeError &e )
{
std::cout << e.what() << std::endl;
}
catch( curlpp::LogicError &e )
{
std::cout << e.what() << std::endl;
}
return 0;
}
The missing symbol _curl_easy_setopt and the curlpp homepage tells me that curlpp is a C++ wrapper around the C library libcurl.
You therefore need to add -lcurl to link with that library too when compiling.
Related
I have recently started working in C++ and came across this situation when I have to create a directory while executing my code. The code is working fine when I have to create a single folder but it fails when I have to create another folder withing this newly created folder.
Suppose, I am in C: and want to store my file in C:/A/B/ .The following piece of code using mkdir() works fine if I have to store my file in C:/A/ but fails when I am adding another folder B.
Following is my code snippet:
#include <sys/stat.h>
#include <string>
using namespace std;
int main()
{
string stringpath = "C:/A/B/";
int status = mkdir(stringpath.c_str(),0777);
if(status!=0)
{
//.....
}
else
{
//....
}
}
Can someone help me in creating this directory where I can have any number of folders inside the parent directory? (P.S:I have added the header files sys/stat.h,iostream and string)
This is how you do it in C++17:
#include <filesystem>
namespace fs = std::filesystem;
fs::create_directories("./a/b/c")
mkdir() creates only the last component of the specified path. In your example, it will create only B. If any of the parent directories do not exist (ie, if A does not exist), the function fails with ENOENT. You need to split up the path and call mkdir() for every intermediate directory in the path, ignoring EEXIST errors as you go.
status = mkdir("C:/A/", 0777);
if ((status < 0) && (errno != EEXIST)) ...
status = mkdir("C:/A/B/", 0777);
if ((status < 0) && (errno != EEXIST)) ...
If you don't want to handle this manually, use a wrapper that handles it for you, such as Boost's create_directories() function:
bool create_directories(const path& p);
bool create_directories(const path& p, system::error_code& ec);
Effects: Establishes the postcondition by calling create_directory() for any element of p that does not exist.
Postcondition: is_directory(p)
Returns: true if a new directory was created, otherwise false.
Throws: As specified in Error reporting.
Complexity: O(n+1)where n is the number of elements of p that do not exist.
You can call the following:
string stringpath = "C:/A/B/";
int status = mkdir(stringpath.c_str(),0777);
If
C:/A/ directory exists. If its not exists, then do the following:
string stringpath = "C:/A/";
int status = mkdir(stringpath.c_str(),0777);
stringpath = "C:/A/B/";
int status = mkdir(stringpath.c_str(),0777);
In C++11 you can use the experimental functios:
#include <experimental/filesystem>
...
std::stringstream bufH;
bufH << dirName << fName;
if (!std::experimental::filesystem::exists(bufH.str()))
{
std::experimental::filesystem::create_directories(bufH.str());
}
Try the octal flag 7777 like this to have all the rights necessary to create this folder.
int status = mkdir(stringpath.c_str(), 7777);
Or do a chmod in the A folder like that :
chmod -r 7777 *
I want to create an output file in a threadsafe manner, and only if it does not exist. I want to use the file system for synchronization. With open() I would use the flags O_RWRONLY|O_CREAT|O_EXCL. Is there a way to do this in C++17 using the iostream or fstream ?
Prior to C++23 there is no way of opening an ofstream in exclusive mode.
Workaround: Use std::fopen which has this capability since C++17.
Example:
#include <cstdio>
// Mode "x" to make it fail if it already exists
std::FILE* fp = std::fopen("filename", "wx");
if(fp) {
// created exclusively
// work with fp ...
std::fclose(fp);
}
If you really want an ofstream you could create a helper function:
template<class Stream>
Stream open_exclusively(const std::string& filename) {
Stream rv;
if(std::FILE* fp = std::fopen(filename.c_str(), "wx"); fp) {
std::fclose(fp);
// overwrite the file that was created exclusively:
rv.open(filename);
} else {
// could not create file exclusivly, set the failbit in the stream:
rv.setstate(Stream::failbit);
}
return rv;
}
int main() {
auto os = open_exclusively<std::ofstream>("filename");
if(os) {
std::cout << "file created exclusively\n";
}
}
Demo
Edit:
Even though the above demo is compliant and works on all platforms I've tested it - wine (v6.16) can't handle it, so I opened a bug report at bugs.winehq.org. You can follow the progress here:
Standard library call fopen(..., "wx") not recognized - causes destruction of data
Edit 2:
The Wine bugfix ucrtbase: Add support for x mode in fopen is now included in Wine 6.20 so after upgrading to 6.20 (or later), this will be working as it should in Wine too.
From C++23 you can use the std::ios::noreplace openmode:
std::ofstream os("filename", std::ios::noreplace);
if(os) {
std::cout << "file created exclusively\n";
}
I'm trying to print the document in a GeckoWebBrowser, but documentation is limited and to me, it's not at all clear.
I found some code on the internet that at least communicates with the printer (it starts beeping) but I think the printer is asking for a Letter size paper, but it requires the settings to be from print.GetGlobalPrintSettingsAttribute(), if I try my own settings, it gives me a NotImplementedException.
I suspect this is exception is raised on my Gecko.PrinterSettings, because when I swap ps in the print.Print(ps, null);
with the global settings, this exception isn't raised.
The code below:
var domWindow = browser.Window.DomWindow;
var print = Gecko.Xpcom.QueryInterface<Gecko.nsIWebBrowserPrint>(domWindow);
Gecko.PrintSettings ps = new Gecko.PrintSettings();
ps.SetPrintSilentAttribute(false);
ps.SetPrintToFileAttribute(false);
ps.SetShowPrintProgressAttribute(false);
ps.SetOutputFormatAttribute(1); //2 == PDF, so I assume 1 is actual printer
ps.SetPrintBGImagesAttribute(true);
ps.SetStartPageRangeAttribute(1);
ps.SetEndPageRangeAttribute(100);
ps.SetPrintOptions(2, true); // evenPages
ps.SetPrintOptions(1, true); // oddpages
ps.SetEffectivePageSize(768 * 20f, 1024 * 20f);
ps.SetShrinkToFitAttribute(true);
ps.SetScalingAttribute(1.0);
ps.SetPrintBGImagesAttribute(true);
print.Print(ps, null);
Managed to come up with a solution.
What was throwing an exception was
public void SetPersistMarginBoxSettingsAttribute(bool aPersistMarginBoxSettings)
{
throw new NotImplementedException();
}
The above is in PrinterSettings.cs, so it is hard-coded coded to throw a NotImplementedException on a number off attributes (the attribute above isn't the only one hard-coded to throw the exception) as it is not finished(?), so I cannot use it.
However, I can use the GetGlobalSettingsAttribute() as it uses the same interface as PrinterSettings (nsiPrintSettings), so therefore it will have the same attributes all populated for me.
So what can I do is:
I simply copy the GetGlobalPrintSettingsAttribute() into my own printer settings, and adjust them as necessary.
var mySettings = print.GetGlobalPrintSettingsAttribute();
mySettings.SetPrintSilentAttribute(true);
mySettings.SetPrintToFileAttribute(true);
mySettings.SetShowPrintProgressAttribute(false);
mySettings.SetOutputFormatAttribute(2); //2 == PDF
mySettings.SetToFileNameAttribute(#"c:\temp\temp.pdf");
mySettings.SetPrintBGImagesAttribute(true);
mySettings.SetStartPageRangeAttribute(1);
mySettings.SetEndPageRangeAttribute(100);
mySettings.SetPrintOptions(2, true); // evenPages
mySettings.SetPrintOptions(1, true); // oddpages
mySettings.SetShrinkToFitAttribute(true);
mySettings.SetScalingAttribute(1.0);
mySettings.SetPrintBGImagesAttribute(true);
print.Print(mySettings, new Gecko.WebProgressListener());
Please notice I reverted back to PDF for now, in the SetOutputFormatAttribute(2); //2 == PDF
Also changed the print.Print(ps, null); to print.Print(mySettings, new Gecko.WebProgressListener()); but I think having null or Gecko.WebProgressListener() won't make a difference.
Et voilà! - Now, onto the next step, which is to print to a printer, and not as a PDF file.
When i launch the php script, sometime works fine, but many other times it retrieve me this errror
Fatal error: Call to a member function children() on a non-object in
/membri/americanhorizon/ytvideo/rilevametadatadaurlyoutube.php on line
21
This is the first part of the code
// set feed URL
$feedURL = 'http://gdata.youtube.com/feeds/api/videos/dZec2Lbr_r8';
// read feed into SimpleXML object
$entry = simplexml_load_file($feedURL);
$video = parseVideoEntry($entry);
function parseVideoEntry($entry) {
$obj= new stdClass;
// get nodes in media: namespace for media information
$media = $entry->children('http://search.yahoo.com/mrss/'); //<----this is the doomed line 21
UPDATE: solution adopted
for ($i=0 ; $i< count($fileArray); $i++)
{
// set feed URL
$feedURL = 'http://gdata.youtube.com/feeds/api/videos/'.$fileArray[$i];
// read feed into SimpleXML object
$entry = simplexml_load_file($feedURL);
if (is_object($entry))
{
$video = parseVideoEntry($entry);
echo ($video->description."|".$video->length);
echo "<br>";
}
else
{
$i--;
}
}
In this mode i force the script to re-check the file that caused the error
You are first of all calling a function:
$entry = simplexml_load_file($feedURL);
That function has a return value. You find it documented on the manual page of that function:
http://php.net/simplexml_load_file
Then you use that return value in form of a variable $entry without verifying that the function call was successful.
Because of that, you run into an error next. However your error/mistake is how you treat the return value of the function.
Not dealing with return values properly is like calling for trouble. Read about the function you use, check the return value(s) and proceed according to success or error conditions.
$entry = simplexml_load_file($feedURL);
if (FALSE === $entry)
{
// youtube not available.
}
else
{
// that's what I love!
}
Sometimes? Really?
Take a look at this:
<?php
$dummy; //IN FACT, this var is NULL now
// Will throw exactly the same error you get
$dummy->children();
Why? Because, we can call method from an object type.
So, if you wanna avoid errors like this one, next time you would call the method ensure that it's "possible".
<?php
if ( is_object($dummy) && method_exists($dummy, 'children') ){
//sure it works
$dummy->children();
}
I pretty much copied this code right out of the MDN File I/O page.. except I added an if statement to check if the file exists already and if it does, read it instead.
Components.utils.import("resource://gre/modules/NetUtil.jsm");
Components.utils.import("resource://gre/modules/FileUtils.jsm");
var file = Components.classes["#mozilla.org/file/directory_service;1"].
getService(Components.interfaces.nsIProperties).
get("Desk", Components.interfaces.nsIFile);
file.append("test.txt");
if (!file.exists()) {
this.user_id = Math.floor(Math.random()*10001) +'-'+ Math.floor(Math.random()*10001) +'-'+ Math.floor(Math.random()*10001) +'-'+ Math.floor(Math.random()*10001);
var ostream = FileUtils.openSafeFileOutputStream(file)
var converter = Components.classes["#mozilla.org/intl/scriptableunicodeconverter"].
createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
var istream = converter.convertToInputStream(this.user_id);
// The last argument (the callback) is optional.
NetUtil.asyncCopy(istream, ostream, function(status) {
if (!Components.isSuccessCode(status)) {
alert('Error '+ status);
return;
}
alert('File created');
});
} else
{
NetUtil.asyncFetch(file, function(inputStream, status) {
if (!Components.isSuccessCode(status)) {
alert('error '+ status);
return;
}
// The file data is contained within inputStream.
// You can read it into a string with
this.user_id = NetUtil.readInputStreamToString(inputStream, inputStream.available());
});
alert('File exists already, do not create');
}
alert(this.user_id);
It creates the file just fine, I can open it and read it. If the file already exists however, it does not populate this.user_id.. just equals null. So my issue is specifically with reading the file.
File reading in your code works asynchronously - meaning that your code completes (including the alert() call which will show that this.user_id is null), then at some point the callback from NetUtil.asyncFetch() gets called with the data. Until that happens this.user_id won't be set of course. If you move alert(this.user_id) into the callback function it should show the correct value.
Note that it is highly recommended to keep file I/O operations asynchronous because they might take significant time depending on the current state of the file system. But you have to structure your code in such a way that it doesn't assume that file operations happen immediately.