views:

293

answers:

5

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);
A: 

You need to read about C++ interop and data marshalling.

Basically: you need to "cast" the .NET String to a C++ TCHAR array.

See this: http://msdn.microsoft.com/en-us/library/ef4c3t39(VS.80).aspx

Computer Guru
A: 

Random Googling got me this. Maybe someone can shorten it?

cli::array<char>^ bytes = Encoding::ASCII::GetBytes(nowString);
pin_ptr<char> pinned = &bytes[0];
std::string nativeString((char*)pinned, bytes->Length);
char const* chars = nativeString.c_str();

Edit: This is longer than the operations of the Marshal class, but works with more encodings. In your case, it sounds like the simpler StringToHGlobalAnsi approach will do everything you need.

280Z28
A: 

You can try sending ToCharArray() to your string

blueberryfields
A: 

Use the StringToXxxAnsi functions in the Marshal class to allocate a char* buffer, then the appropriate functions from the same class to free them.

Koro
+1  A: 

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.

mcdave
Would it be more appropriate to use Marshal::FreeHGlobal() instead of Marshal::FreeCoTaskMem()? My MSDN help for StringToHGlobalAnsi() says use FreeHGlobal() to free the memory.
cmw
Yes, fair call; Edit made. I guess I got into the habit of using FreeCoTaskMem by default.
mcdave