需要将 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
Need to convert String^ to char *
提问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 Marshal
functions!
无需调用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 StringToHGlobalAnsi
approach will do everything you need.
编辑:这比 Marshal 类的操作更长,但可以使用更多编码。在您的情况下,听起来更简单的StringToHGlobalAnsi
方法可以满足您的所有需求。
回答by Koro
Use the StringToXxxAnsi
functions in the Marshal
classto allocate a char*
buffer, then the appropriate functions from the same class to free them.
使用类中的StringToXxxAnsi
函数来分配一个缓冲区,然后使用同一个类中的相应函数来释放它们。Marshal
char*
回答by Mahmoud Al-Qudsi
You need to read about C++ interop and data marshalling.
您需要阅读有关 C++ 互操作和数据编组的信息。
Basically: you need to "cast" the .NET String
to a C++ TCHAR
array.
基本上:您需要将 .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