I run successfully:
Process::Start("C:\\Users\\Demetres\\Desktop\\JoypadCodesApplication.exe");
from a Windows Forms application (visual c++) and as expected, I got 2 programs running simultaneously. My questions is:
Can I pass a string -indicating the file name- to the Process::Start method? I tried:
std::string str="C:\\Users\\Demetres\\Desktop\\JoypadCodesApplication.exe";
Process::Start("%s", str);
but failed. Is this possible?
EDIT:
I think you actually need to marshal to a System::String^ for passing an argument.
You can even marshal directly from a std::string to a System::String^.
///marshal_as<type>(to_marshal)
///marshal_context ctx; ctx.marshal_as<const char *>(to_marshal)
#include <msclr/marshal.h>
#include <msclr/marshal_cppstd.h>
#include <msclr/marshal_atl.h>
using namespace msclr::interop;
using namespace System::Runtime::InteropServices;
Process::Start(marshal_as<String^>(str));
But in this case, you can just use a String^ instead:
String^ str = L"path to file";
Process::Start(str);
When you are working with C++/CLI, you either need to marshal back and forth or use the right data type from the start for how you want to use it.
MSDN: Overview of Marshaling in C++
Process::Start expects a String^ and you are attempting to pass it a std::string. It does not have a variadric version, and does not know what a std::string is. To pass the value from a std::string, you must marshal it:
std::string str("Some Path");
Process::Start(marshal_as<String^>(str));
Related
I am using the casablanca C++ Rest library to make HTTP requests.
The problem is that this gives a utility::string_t string as output and I can't quite find any way to convert this to a classic std::string. Any ideas?
client.request(methods::GET).then([](http_response response)
{
if(response.status_code() == status_codes::OK)
{
string_t s = response.extract_string().get();
}
});
Depending on what platform you are compiling for, the utility::string_t type will be typedef'd to either std::wstring (on Windows) or std::string (on Linux/OSX).
To get a classic utf-8 std::string regardless of platform, take a look at utility::conversions::to_utf8string.
reference documentation
If you see the documentation for C++ REST SDK from github, you'll find a typedef
C++ Rest SDK - utility Namespace Reference
typedef std::string string_t;
So no need to convert it. Both are same types.
On Windows Phone 8.1 there is this define:
typedef std::wstring string_t;
I used this:
string_t toStringT = U("sample");
std::string fromStringT(toStringT.begin(), toStringT.end());
or:
std::string fromStringT(conversions::to_utf8string(toStringT));
I am following the "chat example" from Boost Asio's tutorials. As I don't have much experience with Boost Asio, I am implementing my own client server application using the chat example and modifying it according to my needs.
Now I am defining a Protocol.hpp file, which contains keywords for the network protocol. For example:
Protocol.hpp
#ifndef PROTOCOL_HPP
#define PROTOCOL_HPP
#include <iostream>
extern const char ACK;
#endif
Protocol.cpp
#include "Protocol.hpp"
const char ACK = "1";
If you take a look at the "chat_message.hpp" class, you will find the following:
const char* data() const
{
return data_;
}
char* data()
{
return data_;
}
I have tried the following:
std::sprintf(write_msgs_.data(), ACK, 2);
As well as trying to assign directly the desired code like this —however I guess that I am obtaining the const function—:
write_msgs_.data() = ACK;
I have thought of using the string class and then somehow convert it to char, in order to copy it in the write_msgs_.data(), or even adding every character with a loop. I am relatively new to C++, and I don't seem to find a good solution for this. Is there any proper way of doing this?
Thank you very much in advance.
I found it. I should have checked how the example application does it, and it simply uses memcpy from the cstring library. Therefore, anyone having the same problem as me should use the following:
main of the chat_client.cpp file:
char line[chat_message::max_body_length + 1];
while (std::cin.getline(line, chat_message::max_body_length + 1))
{
using namespace std; // For strlen and memcpy.
chat_message msg;
msg.body_length(strlen(line));
memcpy(msg.body(), line, msg.body_length());
msg.encode_header();
c.write(msg);
}
As you can see there is a char line variable that will hold the written text. After this, memcpy is used to copy the line to the body of the message.
I am using the casablanca C++ Rest library to make HTTP requests.
The problem is that this gives a utility::string_t string as output and I can't quite find any way to convert this to a classic std::string. Any ideas?
client.request(methods::GET).then([](http_response response)
{
if(response.status_code() == status_codes::OK)
{
string_t s = response.extract_string().get();
}
});
Depending on what platform you are compiling for, the utility::string_t type will be typedef'd to either std::wstring (on Windows) or std::string (on Linux/OSX).
To get a classic utf-8 std::string regardless of platform, take a look at utility::conversions::to_utf8string.
reference documentation
If you see the documentation for C++ REST SDK from github, you'll find a typedef
C++ Rest SDK - utility Namespace Reference
typedef std::string string_t;
So no need to convert it. Both are same types.
On Windows Phone 8.1 there is this define:
typedef std::wstring string_t;
I used this:
string_t toStringT = U("sample");
std::string fromStringT(toStringT.begin(), toStringT.end());
or:
std::string fromStringT(conversions::to_utf8string(toStringT));
I have the following function, which will hopefully tell me whether or not a folder exists, but when I call it, I get this error -
cannot convert parameter 1 from 'System::String ^' to 'std::string'
The function -
#include <sys/stat.h>
#include <string>
bool directory_exists(std::string path){
struct stat fileinfo;
return !stat(path.c_str(), &fileinfo);
}
The call (from the form.h file that holds the form where the user selects the folder) -
private:
System::Void radioListFiles_CheckedChanged(System::Object^ sender, System::EventArgs^ e) {
if(directory_exists(txtActionFolder->Text)){
this->btnFinish->Enabled = true;
}
}
Is anyone able to tell me how to filx this? Thanks.
You're trying to convert from a managed, C++/CLI string (System::String^) into a std::string. There is no implicit conversion provided for this.
In order for this to work, you'll have to handle the string conversion yourself.
This will likely look something like:
std::string path = context->marshal_as<std::string>(txtActionFolder->Text));
if(directory_exists(path)) {
this->btnFinish->Enabled = true;
}
That being said, in this case, it might be easier to stick to managed APIs entirely:
if(System::IO::Directory::Exists(txtActionFolder->Text)) {
this->btnFinish->Enabled = true;
}
You are trying to convert a CLR string to a STL string to convert it to a C-string to use it with a POSIX-emulation function. Why such a complication? Since you are using C++/CLI anyway, just use System::IO::Directory::Exists.
To make this work you need to convert from the managed type System::String to the native type std::string. This involves a bit of marshaling and will result in 2 separate string instances. MSDN has a handy table for all of the different types of marshaling for strings
http://msdn.microsoft.com/en-us/library/bb384865.aspx
In this particular case you can do the following
std::string nativeStr = msclr::interop::marshal_as<std::string>(managedStr);
I am using the directory class to get this information but unable to assign this data to a data member of my own class. i am doing an oop project. Furthermore,I want to use the concept of Dynamism(containment).I have created two class, mydirectory and myfiles as under:
class files
{
string fname[25];
public:
files()
{
fname=NULL;
}
};
class directory
{ private:
directory *d;
string *dname[25]; //* to show there may be a subdirectory,there may be not.
files *ff[25]; // data member string *fname[25];
int numd,numf;
public:
directory()
{
numd=0;numf=0;
}
Now when if I want to use the statment:
Directory::GetDirectories("D:\\");
how can I assign the directory names to "dname" of directory class.
I dont want to include a third party software.
also i need help on the topic: how can a file (doc file/pdf/txt/pwt etc) can be opened from c++ code outside the console? I am very worried. please help me. thanks in advance.
I am new to c++ so please forgive if there are any errors in pointer handling, as I am doing this containment for the first time. I also need some reading stuff.
The simplest way to do it in C++ is using boost::filesystem.
As long as the path is a directory you can iterate over it using either a directory_iterator or a recursive_directory_iterator.
eg:
boost::filesystem::path dirname( "D:\\" );
std::vector<boost::filesystem::path> topLevel( directory_iterator(dirName),
directory_iterator() );
std::vector<boost::filesystem::path> wholeDrive(
recursive_directory_iterator(dirName), recursive_directory_iterator() );
As this is marked homework, we're not going to be helping you much by giving you the correct answer. But I will point you in the right direction.
You've indicated you're doing this under Visual C++. Well without using any third party libraries but just what's built in, you'll need to access the Win32 API.
FindFirstFile() & FindNextFile() are what you need.
You'll call FindFirstFile first off to obtain the directory handle.
The parameter is the D:\ that you're passing into your class.
Then call FindNextFile in a while loop.
e.g. The basic principle of using those API's is
HANDLE h = FindFirstFile("D:\\");
WIN32_FIND_DATA data;
while (FindNextFile(h, &data))
{
// Check if it's a directory or not
if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
// Add to dname
}
}
Consider using std::vector for your dname instead of string*
because you're stuck with 25 entries. Using vector it'll grow for you.
As said CashCow, boost::filesystem
As a general rule, in C++ for such examples, you don't need any pointer. Here a some mistakes you should correct:
string fname[25];
This declares an array of 25 strings. You probably wanted a string of 25 chars ? Well, in std::string, you don't need to care about the length. std::string fname; is enough
std::string file_name;
file_name = "baz.txt";
fname=NULL;
If fname is a string, then it's not a pointer. So you can't assign NULL to it. A std::string is by default initialized as an empty string. You can leave the whole constructor out.
string *dname[25]
I suppose you wanted to have an array of string. Just use :
std::vector<std::string> dnames;
dnames.push_back("foo");
dnames.push_back("bar"); // dnames now contains {"foo","bar"}
And you'll have a dynamically resizable vector of strings.
See : no need of any pointer. No need for any new
Finally I completed the short project.To get the list of files and sub directories, I made use of .NET Framework namespace "System".It has got classes like "FileInfo" and "DirectoryInfo"(both belong to System::IO) which do the above required task.But here,all the string related stuff is of System::String , not of std::string.To convert System::String to std::string, I used the following code(I got this conversion's code from a forum and it worked fine without any error):
string Str2str(String ^a)
{
array<Byte> ^chars = System::Text::Encoding::ASCII->GetBytes(a);
pin_ptr<Byte> charsPointer = &(chars[0]);
char *nativeCharsPointer = reinterpret_cast<char *>(static_cast<unsigned char *>(charsPointer));
string native(nativeCharsPointer, chars->Length);
return native;
}
Here is a short code for getting list of sub directories from a drive(D: drive is going to be searched):
#include<iostream>
#using<mscorlib.dll>
using namespace strd;
using namespace System;
using namespace System::IO;
int main()
{int count=50;
string name[count];//to hold directories names
string b;
int s=0;
DirectoryInfo^ di = gcnew DirectoryInfo("d:\\");
if(di->Exists)
{array<DirectoryInfo^>^diArr = di->GetDirectories();
Collections::IEnumerator^ myEnum = diArr->GetEnumerator();
while ( myEnum->MoveNext() )
{DirectoryInfo^ dri = safe_cast<DirectoryInfo^>(myEnum->Current);
String ^a=(dri->Name->ToString());
int n=b.size();
b=Str2str(a); `// code given in the starting`
if (s<count)
{name[s]=b;
s++;}
}
This involves Managed C++ knowledge. Visit these:
.NET Programming Guide
C++: The Most Powerful Language for .NET Framework Programming
I compiled this on Visual Studio 2008. I will be very grateful if you appriciate my effort.Further suggestions are most welcomed.