需要将 String^ 转换为 char *

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2178023/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 00:37:27  来源:igfitidea点击:

Need to convert String^ to char *

stringc++-clichar

提问by kman99

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

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

回答by mcdave

Your best bet is to use StringToHGlobalAnsi. Here is complete code showing how its done and remembering to free the memory allocated.

最好的办法是使用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);
}

You might want to rethink using a ':' character in the filename, as I don't believe windows likes this very much.

您可能需要重新考虑在文件名中使用 ':' 字符,因为我不相信 Windows 非常喜欢这个。

回答by Ionian316

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 *从 a获取 a 的最简单方法String^是使用 good ol' 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);

No need to call the Marshalfunctions!

无需调用Marshal函数!

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:

所以看起来 VS 2015 更接近于 C++11 标准,所以sprintf()与 .NET String 一起使用是行不通的。最简单的方法是使用这样的marshal_as()函数:

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:

否则,如果您不想使用该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]);
}

回答by Sam Harwell

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 StringToHGlobalAnsiapproach will do everything you need.

编辑:这比 Marshal 类的操作更长,但可以使用更多编码。在您的情况下,听起来更简单的StringToHGlobalAnsi方法可以满足您的所有需求。

回答by Koro

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

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

回答by Mahmoud Al-Qudsi

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

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

Basically: you need to "cast" the .NET Stringto a C++ TCHARarray.

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

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

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