Необходимо преобразовать строку ^ в символ * - PullRequest
11 голосов
/ 01 февраля 2010

Я использую .NET DateTime для получения текущей даты и времени.Я преобразую его в строку для использования в качестве части имени файла.Проблема заключается в том, что команда OpenCV для сохранения изображения требует символ *, а не строковый тип, а DateTime будет выводить только тип String ^.Как мне сделать эту работу?Вот код не завершен

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

Ответы [ 5 ]

16 голосов
/ 02 февраля 2010

Лучше всего использовать StringToHGlobalAnsi. Вот полный код, показывающий, как это делается, и память о выделении свободной памяти.

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

Возможно, вы захотите переосмыслить, используя символ «:» в имени файла, поскольку я не верю, что Windows это очень нравится.

5 голосов
/ 23 января 2015

На самом деле, я нашел самый простой способ получить char * от String^ - это использовать доброе старое sprintf(). Так что в вашем случае вы можете просто сделать это:

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

Нет необходимости вызывать функции Marshal!

Обновление

Похоже, что VS 2015 более тесно соответствует стандартам C ++ 11, поэтому использование sprintf() с .NET String не будет работать. Самый простой способ - использовать функцию marshal_as() следующим образом:

Включите эти строки перед вашим кодом:

#include <msclr/marshal_cppstd.h>
using namespace msclr::interop;

Тогда это должно работать:

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

В противном случае, если вы не хотите использовать функцию marshal_as(), вы можете скопировать строковый символ за символом, например так:

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]);
}
0 голосов
/ 01 февраля 2010

Случайный поиск в Google дал мне это.Может быть, кто-то может сократить его?

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

Редактировать: Это больше, чем операции класса Marshal, но работает с большим количеством кодировок.В вашем случае кажется, что более простой подход StringToHGlobalAnsi сделает все, что вам нужно.

0 голосов
/ 01 февраля 2010

Используйте функции StringToXxxAnsi в классе Marshal , чтобы выделить буфер char*, затем соответствующие функции из того же класса, чтобы освободить их.

0 голосов
/ 01 февраля 2010

Вам нужно прочитать о взаимодействии C ++ и распределении данных.

В основном: вам нужно "привести" .NET String к массиву C ++ TCHAR.

См. Это: http://msdn.microsoft.com/en-us/library/ef4c3t39(VS.80).aspx

...