I am using the .NET DateTime to get the current date and time. I am converting it to a string to use as part of a file name. The problem is the OpenCV command to save an image requires a char * not a string type, and DateTime will only output a String^ type. How do I make this work? Heres the code not completed
String^ nowString = DateTime::Now.ToString("yyyy-MM-dd-HH:mm");
IplImage* toSave;
CvCapture* capture = cvCreateCameraCapture(0);
toSave = cvQueryFrame( capture );
cvSaveImage(nowString, toSave);
cvReleaseImage(&toSave);
cvReleaseCapture(&capture);
Yes, char* is the pointer to an array of character, which is a string.
We can convert String to char in java using charAt() method of String class. The charAt() method returns a single character only. To get all characters, you can use loop.
You can't really "assign a string" to a char * , because although a char* parameter is sometimes referred to as a "string parameter", it isn't actually a string, it's a pointer (to a string). If you're getting heap corruption, then the problem isn't the assignment, the problem is your management of allocated memory.
char* is typically used to iterate through a character array, i.e., a C string. It is rarely used as a pointer to a single char, unlike how other pointers are typically used. C++ has newer constructs for strings that typically should be used.
Your best bet is to use StringToHGlobalAnsi
. Here is complete code showing how its done and remembering to free the memory allocated.
using namespace System::Runtime::InteropServices;
void MethodName()
{
String^ nowString = DateTime::Now.ToString("yyyy-MM-dd-HH:mm");
IntPtr ptrToNativeString = Marshal::StringToHGlobalAnsi(nowString);
try
{
CvCapture* capture = cvCreateCameraCapture(0);
IplImage* toSave = cvQueryFrame(capture);
cvSaveImage(static_cast<char*>(ptrToNativeString.ToPointer()), toSave);
cvReleaseImage(&toSave);
cvReleaseCapture(&capture);
}
catch (...)
{
Marshal::FreeHGlobal(ptrToNativeString);
throw;
}
Marshal::FreeHGlobal(ptrToNativeString);
}
You might want to rethink using a ':' character in the filename, as I don't believe windows likes this very much.
Actually, I found the easiest way to get a char *
from a String^
is to use good ol' sprintf()
. So in your case, you can simple do this:
char cNow[17] = { 0 };
String^ nowString = DateTime::Now.ToString("yyyy-MM-dd-HH:mm");
if (nowString->Length < sizeof(cNow)) // make sure it fits & allow space for null terminator
sprintf(cNow, "%s", nowString);
No need to call the Marshal
functions!
Update
So it appears that VS 2015 adheres more closely to the C++11 standards, so using sprintf()
with the .NET String won't work. The easiest way is to use the marshal_as()
function like this:
Include these lines before your code:
#include <msclr/marshal_cppstd.h>
using namespace msclr::interop;
Then this should work:
char cNow[17] = { 0 };
String^ nowString = DateTime::Now.ToString("yyyy-MM-dd-HH:mm");
string sNow = marshal_as<string>(nowString);
if (sNow.length() < sizeof(cNow)) // make sure it fits & allow space for null terminator
sprintf(cNow, "%s", sNow.c_str());
Otherwise, if you don't want to use the marshal_as()
function, you can copy the string character by character like this:
char cNow[17] = { 0 };
String^ nowString = DateTime::Now.ToString("yyyy-MM-dd-HH:mm");
if (nowString->Length < sizeof(cNow)) // make sure it fits & allow space for null terminator
{
for (int i = 0; i < nowString->Length; i++)
cNow[i] = static_cast<char>(nowString[i]);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With