I'm currently working on a metro app that requires a few textual resources. Part of the build process is copying all of these resources to a folder inside of the app's installation directory. What I'd like to do is gather a list of these resource files, and process each one accordingly. Unfortunately, my attempts to do so have been less than successful.
Since I'm building for WinRT, I can't use the very useful "FindFirstFile" and "FindNextFile" functions. I've been trying to get the job done using the WinRT Asynchronous file IO operations.
auto getResourceFolder = installedLocation->GetFolderFromPathAsync( folderPath );
getResourceFolder->Completed = ref new Windows::Foundation::AsyncOperationCompletedHandler< Windows::Storage::StorageFolder^ >(
[this]( Windows::Foundation::IAsyncOperation< Windows::Storage::StorageFolder^ >^ operation ) {
if( operation->Status == Windows::Foundation::AsyncStatus::Completed ) {
auto resourceFolder = operation->GetResults();
auto getResourceFiles = resourceFolder->GetFilesAsync();
getResourceFiles->Completed = ref new Windows::Foundation::AsyncOperationCompletedHandler< IVectorView< Windows::Storage::IStorageFile^ >^ >(
[this]( Windows::Foundation::IAsyncOperation< IVectorView< Windows::Storage::IStorageFile^ >^ >^ operation ) {
if( operation->Status == Windows::Foundation::AsyncStatus::Completed ) {
auto resourceFiles = operation->GetResults();
for( unsigned int i = 0; i < resourceFiles->Size; ++i ) {
// Process File
}
}
});
}
});
Which fails to compile:
error C2664: 'Windows::Foundation::IAsyncOperation<TResult>::Completed::set' : cannot convert parameter 1 from 'Windows::Foundation::AsyncOperationCompletedHandler<TResult> ^' to 'Windows::Foundation::AsyncOperationCompletedHandler<TResult> ^'
The error isn't making any sense to me. I've tried rewriting the above code so that the lambda handler functions are not inline, but it hasn't made a difference. I'm not sure what's wrong.
Any ideas? Thanks in advance.
[Note: I have omitted most namespace qualification from the code and error messages for brevity.]
The Visual Studio Error List pane only shows the first line of each error (this is a very useful feature, especially when programming in C++, because some error messages from the compiler are exceedingly long. You need to look at the Output window to see the rest of the error message:
error C2664: 'IAsyncOperation<TResult>::Completed::set' :
cannot convert parameter 1
from 'AsyncOperationCompletedHandler<TResult> ^'
to 'AsyncOperationCompletedHandler<TResult> ^'
with
[
TResult=IVectorView<StorageFile ^> ^
]
and
[
TResult=IVectorView<IStorageFile ^> ^
]
and
[
TResult=IVectorView<StorageFile ^> ^
]
No user-defined-conversion operator available, or
Types pointed to are unrelated;
conversion requires reinterpret_cast, C-style cast or function-style cast
This is still a bit confusing because all three templates use a parameter named TResult. To decipher the error, note that the order of the templates in the first line matches the order of the template argument lists in the rest of the line.
The issue here is that you are mixing usage of StorageFile and IStorageFile. On both of these lines, you need to use StorageFile (see carrots under lines for where IStorageFile is used):
getResourceFiles->Completed = ref new Windows::Foundation::AsyncOperationCompletedHandler< IVectorView< Windows::Storage::IStorageFile^ >^ >(
^
[this]( Windows::Foundation::IAsyncOperation< IVectorView< Windows::Storage::IStorageFile^ >^ >^ operation ) {
^
Note that once you fix this issue, you'll get another pair of errors because your lambdas need to have two parameters; the second is an AsyncStatus. In the end, they should both be declared as:
// Namespaces omitted for brevity
[this](IAsyncOperation<StorageFolder^>^ operation, AsyncStatus status) { }
Since I'm building for WinRT, I can't use the very useful FindFirstFile and FindNextFile functions.
Note that you can, in fact, use both FindFirstFileEx and FindNextFile in a Metro style app. (The non-Ex FindFirstFile is not usable).
You should use the asynchronous WinRT functions wherever you can and wherever it is practical, but that doesn't mean there isn't still a use for these other functions.
A far simpler solution is to use PPL for your async operations. Instead of manually rolling the async operation, try:
create_task(installedLocation->GetFolderFromPathAsync(folderPath)
.then([this](Windows::Storage::StorageFolder^ folder) {
return folder->GetFilesAsync();
})
.then([this](IVectorView<Windows::Storage::StorageFile^ >^ files) {
for( unsigned int i = 0; i < files->Size; ++i ) {
// Process File
}
});
I'm not 100% on the syntax, this was written in the SO code editor, but it shows how PPL dramatically reduces the complexity of this kind of code - basically you use create_task to create a task, then use the .then method on the task to specify a lambda which is used for async completion.
EDIT: Updated to remove the nested lambda.
Related
I am writing multi-threaded server that handles async read from many tcp sockets. Here is the section of code that bothers me.
void data_recv (void) {
socket.async_read_some (
boost::asio::buffer(rawDataW, size_t(648*2)),
boost::bind ( &RPC::on_data_recv, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
} // RPC::data_recvW
void on_data_recv (boost::system::error_code ec, std::size_t bytesRx) {
if ( rawDataW[bytesRx-1] == ENDMARKER { // <-- this code is fine
process_and_write_rawdata_to_file
}
else {
read_socket_until_endmarker // <-- HELP REQUIRED!!
process_and_write_rawadata_to_file
}
}
Nearly always the async_read_some reads in data including the endmarker, so it works fine. Rarely, the endmarker's arrival is delayed in the stream and that's when my program fails. I think it fails because I have not understood how boost bind works.
My first question:
I am confused with this boost totorial example , in which "this" does not appear in the handler declaration. ( Please see code of start_accept() in the example.) How does this work? Does compiler ignore the "this" ?
my second question:
In the on_data_recv() method, how do I read data from the same socket that was read in the on_data() method? In other words, how do I pass the socket as argument from calling method to the handler? when the handler is executed in another thread? Any help in form of a few lines of code that can fit into my "read_socket_until_endmarker" will be appreciated.
My first question: I am confused with this boost totorial example , in which "this" does not appear in the handler declaration. ( Please see code of start_accept() in the example.) How does this work? Does compiler ignore the "this" ?
In the example (and I'm assuming this holds for your functions as well) the start_accept() is a member function. The bind function is conveniently designed such that when you use & in front of its first argument, it interprets it as a member function that is applied to its second argument.
So while a code like this:
void foo(int x) { ... }
bind(foo, 3)();
Is equivalent to just calling foo(3)
Code like this:
struct Bar { void foo(int x); }
Bar bar;
bind(&foo, &bar, 3)(); // <--- notice the & before foo
Would be equivalent to calling bar.foo(3).
And thus as per your example
boost::bind ( &RPC::on_data_recv, this, // <--- notice & again
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)
When this object is invoked inside Asio it shall be equivalent to calling this->on_data_recv(error, size). Checkout this link for more info.
For the second part, it is not clear to me how you're working with multiple threads, do you run io_service.run() from more than one thread (possible but I think is beyond your experience level)? It might be the case that you're confusing async IO with multithreading. I'm gonna assume that is the case and if you correct me I'll change my answer.
The usual and preferred starting point is to have just one thread running the io_service.run() function. Don't worry, this will allow you to handle many sockets asynchronously.
If that is the case, your two functions could easily be modified as such:
void data_recv (size_t startPos = 0) {
socket.async_read_some (
boost::asio::buffer(rawDataW, size_t(648*2)) + startPos,
boost::bind ( &RPC::on_data_recv, this,
startPos,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
} // RPC::data_recvW
void on_data_recv (size_t startPos,
boost::system::error_code ec,
std::size_t bytesRx) {
// TODO: Check ec
if (rawDataW[startPos + bytesRx-1] == ENDMARKER) {
process_and_write_rawdata_to_file
}
else {
// TODO: Error if startPos + bytesRx == 648*2
data_recv(startPos + bytesRx);
}
}
Notice though that the above code still has problems, the main one being that if the other side sent two messages quickly one after another, we could receive (in one async_read_some call) the full first message + part of the second message, and thus missing the ENDMARKER from the first one. Thus it is not enough to only test whether the last received byte is == to the ENDMARKER.
I could go on and modify this function further (I think you might get the idea on how), but you'd be better off using async_read_until which is meant exactly for this purpose.
I'm been trying to start doing a plug-in for a program called "Euroscope" for quite some time and i still can't do anything. I even read a C++ book and nothing, it's too difficult to start.
The question i'm going to ask is a little bit specific and it's going to be difficult to explain but i'm tired of trying to solve this by my own so here it comes.
I have a class that i imported with a bunch of function prototypes in the header called "EuroscopePlugIn".
My principal .cpp is this:
void CPythonPlugInScreen::meu()
{
//loop over the planes
EuroScopePlugIn::CAircraft ac;
EuroScopePlugIn::CAircraftFlightPlan acfp;
CString str;
CPythonPlugIn object;
for(ac=GetPlugIn()->AircraftSelectFirst();
ac.IsValid();
ac=GetPlugIn()->AircraftSelectNext(ac))
{
EuroScopePlugIn::CAircraftPositionData acpos=ac.GetPosition();
const char *c=ac.GetCallsign();
object.printtofile_simple_char(*c);
object.printtofile_simple_int(ac.GetState());
};
object.printtofile_simple_int(ac.GetVerticalSpeed());
object.printtofile_simple_int(acfp.GetFinalAltitude());
cout<<acfp.GetAlternate();
}
the "printtofile_simple_int" and "printtofile_simple_char" are defined is the class CPythonPlugIn like this:
void printtofile_simple_int(int n){
ofstream textfile;
textfile.open("FP_simple_int.txt");
textfile<<(n);
textfile.close();
So i open the program, load the .dll i created with Build->Solution and it does nothing, the .txt files aren't even created and even the cout produces nothing.
I will give you some of the prototype infos on the header file "EuroScopePlugIn.h" in case you need them to understand my micro program. If you need other,ask me and i'll put it here
//---GetPlugIn-----------------------------------------------------
inline CPlugIn * GetPlugIn ( void )
{
return m_pPlugIn ;
} ;
&
CAircraft AircraftSelectFirst ( void ) const ;
//-----------------------------------------------------------------
// Return :
// An aircraft object instance.
//
// Remark:
// This instance is only valid inside the block you are querying.
// Do not save it to a static place or into a member variables.
// Subsequent use of an invalid extracted route reference may
// cause ES to crash.
//
// Description :
// It selects the first AC in the list.
//-----------------------------------------------------------------
&
int GetFinalAltitude ( void ) const ;
//-----------------------------------------------------------------
// Return :
// The final requested altitude.
//-----------------------------------------------------------------
Please guys i need help to start with the plug-in making, from that point on with a methodology of trial and error i'll be on my way. I'm just finding it extremely hard to start...
Thank you very much for the help
The following line has the error Default argument is not allowed.
public ref class SPlayerObj{
private:
void k(int s = 0){ //ERROR
}
}
Why C++ has no default argument on managed types ?
I would like to know if there is a way to fix this.
It does have optional arguments, they just don't look the same way as the C++ syntax. Optional arguments are a language interop problem. It must be implemented by the language that makes the call, it generates the code that actually uses the default argument. Which is a tricky problem in a language that was designed to make interop easy, like C++/CLI, you of course don't know what language is going to make the call. Or if it even has syntax for optional arguments. The C# language didn't until version 4 for example.
And if the language does support it, how that compiler knows what the default value is. Notable is that VB.NET and C# v4 chose different strategies, VB.NET uses an attribute, C# uses a modopt.
You can use the [DefaultParameterValue] attribute in C++/CLI. But you shouldn't, the outcome is not predictable.
In addition to the precise answer from Hans Passant, the answer to the second part on how to fix this, you are able to use multiple methods with the same name to simulate the default argument case.
public ref class SPlayerObj {
private:
void k(int s){ // Do something useful...
}
void k() { // Call the other with a default value
k(0);
}
}
An alternative solution is to use the [OptionalAttribute] along side a Nullable<int> typed parameter. If the parameter is not specified by the caller it will be a nullptr.
void k([OptionalAttribute]Nullable<int>^ s)
{
if(s == nullptr)
{
// s was not provided
}
else if(s->HasValue)
{
// s was provided and has a value
int theValue = s->Value;
}
}
// call with no parameter
k();
// call with a parameter value
k(100);
I am just trying to compile a bit bigger project using the Visual Studio 2012 Release Candidate, C++. The project was/is compiled using the VS2010 now. (I am just greedy to get the C++11 things, so I tried. :)
Apart of things that I can explain by myself, the project uses the code like this:
ostringstream ostr;
ostr << "The " __FUNCTION__ "() failed to malloc(" << i << ").";
throw bad_alloc(ostr.str().c_str());
The compiler now complains
error C2248: 'std::bad_alloc::bad_alloc' : cannot access private member declared
in class 'std::bad_alloc'
... which is true. That version of constructor is now private.
What was the reason to make that version of constructor private? Is it recommended by C++11 standard not to use that constructor with the argument?
(I can imagine that if allocation failed, it may cause more problems to try to construct anything new. However, it is only my guess.)
Thanks,
Petr
The C++11 Standard defines bad_alloc as such (18.6.2.1):
class bad_alloc : public exception {
public:
bad_alloc() noexcept;
bad_alloc(const bad_alloc&) noexcept;
bad_alloc& operator=(const bad_alloc&) noexcept;
virtual const char* what() const noexcept;
};
With no constructor that takes a string. A vendor providing such a constructor would make the code using it not portable, as other vendors are not obliged to provide it.
The C++03 standard defines a similar set of constructors, so VS didn't follow this part of the standard even before C++11. MS does try to make VS as standard compliant as possible, so they've probably just used the occasion (new VS, new standard) to fix an incompatibility.
Edit: Now that I've seen VS2012's code, it is also clear why the mentioned constructor is left private, instead of being completely removed: there seems to be only one use of that constructor, in the bad_array_new_length class. So bad_array_new_length is declared a friend in bad_alloc, and can therefore use that private constructor. This dependency could have been avoided if bad_array_new_length just stored the message in the pointer used by what(), but it's not a lot of code anyway.
If you are accustomed to passing a message when you throw a std::bad_alloc, a suitable technique is to define an internal class that derives from std::bad_alloc, and override ‘what’ to supply the appropriate message.
You can make the class public and call the assignment constructor directly, or make a helper function, such as throw_bad_alloc, which takes the parameters (and additional scalar information) and stores them in the internal class.
The message is not formatted until ‘what’ is called. In this way, stack unwinding may have freed some memory so the message can be formatted with the actual reason (memory exhaustion, bad request size, heap corruption, etc.) at the catch site. If formatting fails, simply assign and return a static message.
Trimmed example:
(Tip: The copy constructor can just assign _Message to nullptr, rather than copy the message since the message is formatted on demand. The move constructor, of course can just confiscate it :-).
class internal_bad_alloc: public std::bad_alloc
{
public:
// Default, copy and move constructors....
// Assignment constructor...
explicit internal_bad_alloc(int errno, size_t size, etc...) noexcept:
std::bad_alloc()
{
// Assign data members...
}
virtual ~internal_bad_alloc(void) noexcept
{
// Free _Message data member (if allocated).
}
// Override to format and return the reason:
virtual const char* what(void) const noexcept
{
if (_Message == nullptr)
{
// Format and assign _Message. Assign the default if the
// format fails...
}
return _Message;
}
private:
// Additional scalar data (error code, size, etc.) pass into the
// constructor and used when the message is formatted by 'what'...
mutable char* _Message;
static char _Default[];
}
};
//
// Throw helper(s)...
//
extern void throw_bad_alloc(int errno, size_t size, etc...)
{
throw internal_bad_alloc(errno, size, etc...);
}
VERSION 1
class Doh {
private:
static std::map<const std::string, const Doh*> someMap;
std::string stringValue_;
public:
Doh(std::string str) : stringValue_(str) {
Doh::someMap.insert(
std::make_pair<const std::string,const Doh*>
(this->stringValue_,this)
);
}
}
The above was ok with MSVC 2010 but with MSVC 2008 it fails – and I guess it is because the object is not constructed yet when it is inserted in the map (I got a memory access violation).
So, I tried a delayed insertion, which worked:
VERSION 2
Doh(std::string str) : stringValue_(str) {
boost::thread(&Doh::insertIntoTheStaticMap,this);
}
void insertIntoTheStaticMap() {
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
Doh::someMap.insert(
std::make_pair<const std::string,const Doh*>
(this->stringValue_,this)
);
}
But as you might be able to guess, my intention is to have the static Doh::someMap as a common lookup dictionary.
VERSION 1 didn’t need any thread-safety because I would create all Doh instances in the same thread – in initialization blocks - which would be called by dynamic initializers before I enter main().
But with VERSION 2, the naïve sleep() is neither graceful nor reliable (not to mention, I might need to lock the map before insertion).
What would be a nice KISS approach?
Only potential issue I see is the initialization of the static member, if there are multiple source files. Try guarding it with a function.
class Doh {
private:
static std::map< std::string, Doh * > &get_map() {
static std::map< std::string, Doh * > someMap;
return someMap; // initialize upon first use
}
std::string stringValue_;
public:
Doh(std::string str) : stringValue_(str) {
get_map().insert(
std::make_pair
(this->stringValue_,this)
);
}
};
In neither version is there any sign of init for stringvalue_ - what does the debugger show you about this key when you hit the map insert in version 1 of the code? How is this field set up, and what is its type?
Running this in the debugger for VS2008 should allow you to narrow down the point of failure into the <map> source, I would have thought.