需要将String ^转换为char *

时间:2010-02-01 16:00:22

标签: string c++-cli char

我正在使用.NET DateTime来获取当前的日期和时间。我正在将其转换为字符串,以用作文件名的一部分。问题是保存图像的OpenCV命令需要char *而不是字符串类型,而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 个答案:

答案 0 :(得分:16)

最好的办法是使用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非常喜欢这个。

答案 1 :(得分:5)

实际上,我发现从char *获取String^的最简单方法是使用好的&#39; 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]);
}

答案 2 :(得分:0)

您需要阅读有关C ++互操作和数据编组的信息。

基本上:您需要将.NET String“强制转换”为C ++ TCHAR数组。

请参阅:http://msdn.microsoft.com/en-us/library/ef4c3t39(VS.80).aspx

答案 3 :(得分:0)

随机谷歌搜索让我知道了这一点。也许有人可以缩短它?

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方法将完成您所需的一切。

答案 4 :(得分:0)

使用Marshal class中的StringToXxxAnsi函数分配char*缓冲区,然后使用同一类中的相应函数来释放它们。