Need to convert String^ to char *

五迷三道 提交于 2019-11-28 07:15:35

问题


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

回答1:


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.




回答2:


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]);
}



回答3:


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.




回答4:


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




回答5:


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



来源:https://stackoverflow.com/questions/2178023/need-to-convert-string-to-char

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!