我正在使用.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);
答案 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*
缓冲区,然后使用同一类中的相应函数来释放它们。