String 字符串^到VC+中的LPCTSTR+;2010(Windows窗体应用程序)

String 字符串^到VC+中的LPCTSTR+;2010(Windows窗体应用程序),string,c++-cli,file-copying,String,C++ Cli,File Copying,如何将System::string^转换为LPCTSTR? 由于我的要求是使用函数CopyFile克隆一个文件,所以如果我给它的参数指定了Fix name(OldFile.jpg和LatestFile.jpg)(下面的代码是:works fine) 上面的代码将旧的.jpeg克隆到最新的.jpg,但当我试图给出从某个字符串中产生的名称(Latest.jpg)时,它不会创建文件(下面的代码:不工作) 问题是CopyFile将LPCTSTR type作为参数,其中我给出了一个类型System::st

如何将System::string^转换为LPCTSTR? 由于我的要求是使用函数CopyFile克隆一个文件,所以如果我给它的参数指定了Fix name(OldFile.jpg和LatestFile.jpg)(下面的代码是:works fine)

上面的代码将旧的.jpeg克隆到最新的.jpg,但当我试图给出从某个字符串中产生的名称(Latest.jpg)时,它不会创建文件(下面的代码:不工作

问题是CopyFile将LPCTSTR type作为参数,其中我给出了一个类型System::string^,因此建议我如何将System::string^转换为LPCTSTR,以便在文件名中添加当前日期时间。
我正在使用VC++2010和Windows窗体应用程序

您需要将其封送到“const char*”并对LPCTSTR进行静态转换


看看这个

您需要在名称字符串的末尾附加一个\0字符,因为CopyFile()需要零结尾字符串

编辑:正如Lucastzesniewski所指出的,固定.NET字符串会自动生成以零结尾的字符数组。这在C#规范中有记录。有关更多信息,请参阅下面的评论

此外,您必须将字符串“固定”在内存中,这样垃圾收集器就不会四处移动它。然后可以创建指向字符串第一个字符的指针。C++/CLI提供了一些实用程序类型和函数来实现这一点。下面是一个例子:

pin_ptr<const WCHAR> psName = PtrToStringChars (Name)
pin_ptr psName=PtrToStringChars(名称)
PtrToStringChars()是vcclr.h中声明的内联函数。psName应可分配给LPCTSTR参数-如果不是,则使用强制转换。请注意,如果输入字符串为nullptr,则PtrToStringChars()不起作用。您需要针对这种情况进行显式测试。(但是,在您的情况下,Name肯定不是null ptr)


字符串保持固定状态,直到变量psName超出范围。这发生在离开声明它的{…}块之后,例如离开当前函数之后。不需要显式取消钉扎。

标准警告:虽然可以使用C++/CLI编写应用程序的主体,甚至可以使用WinForms在C++/CLI中编写GUI,但不建议这样做。C++/CLI是用于互操作场景的:C++或其他.NET代码需要与非托管C++接口,C++/CLI可以提供两者之间的转换。对于主要开发,如果需要托管代码,则建议使用Cype或WiFrm或WPF,或者如果您想要非托管的,则使用MFC C++。
我不确定我是否同意Hans关于TCHAR已经过时的评论,但将其显式转换为宽字符串并调用
CopyFileW
是一个不错的选择

此外,还可以转到另一个方向,将非托管字符串转换为托管字符串,并使用.Net方法复制文件

要转换为
LPCTSTR
,我将使用marshal\u作为。因为它是用模板实现的,编译器将根据需要解析
LPCTSTR
以调用
LPCSTR
LPCWSTR
版本

Microsoft没有为每个模板化版本的
marshal_as
提供专门的文档页面,但该页面是一个很好的起点

我的测试程序:

#include <msclr\marshal.h>

int main(array<System::String^>^ args)
{
    String^ managedStr = "I came from managed land!\r\n";

    // This controls the lifetime of the LPCTSTR that marshal_as returns. 
    // When this goes out of scope, the LPCTSTR will no longer be valid, 
    // so be aware of its lifetime.
    msclr::interop::marshal_context context;

    LPCTSTR unmanagedStr = context.marshal_as<LPCTSTR>(managedStr);

    OutputDebugString(unmanagedStr);

    return 0;
}

如何,然后从数组中获取指向字符的指针?使用Marshal::StringToHGlobalAnsi或StringToHGlobalUnicode,具体取决于构建时是否使用UNICODE。一定要努力摆脱tchar,它已经过时得无可救药了,请使用CopyFileW,这样您就可以依赖LPCWSTR了。当然,要考虑使用文件::Copy.()而不是所有这些都是必要的。在.NET使用方法中,这个解决方案是有效的,只有使用“StruttoHigLalAluni”而不是“StrugtoHigLalAudioCudie”,并且关闭“McSal::FrHiGuffic”,不需要添加null终止符,因为.NET字符串已经有一个。固定是最轻量级的解决方案,因为它不需要复制字符串。只有设置了UNICODE,字符串才可分配给LPCWSTR或LPCTSTR,除非您正在为Windows 98开发。。。不过最好显式使用LPCWSTR。我在ECMA-335中找不到这方面的参考,这让我很惊讶。但是它肯定是在.NET中实现的:C规范明确地表示:通过修复
字符串
实例生成的
char*
值总是指向以null结尾的字符串。[…]当调用期望“C风格”字符串的外部API时,字符串的自动空终止特别方便。(C#
char
与C++中的
wchar\u t
相同)@Medinoc根据Microsoft帮助,VS 2010上提供了PtrToStringChars():这是将字符串指针从托管传递到非托管的最有效方法,因为它不需要复制字符串。PtrToStringChars()是一个简单的内联函数:它将字符串^强制转换为字节数组,然后添加神奇的偏移量
System::Runtime::CompilerServices::RuntimeHelpers::offsetostringdata
,并将结果指针强制转换回
const WCHAR*
。它几乎不能再快了。@SBS当然它很快,但它要求您显式地使用CopyFileW而不是CopyFile,或者是那个混音而不匹配的家伙。@Medinoc只要您不需要以Windows 98为目标,UNICODE开关无论如何都会被翻转。坦率地说,我上一次使用Windows ANSI函数大约是15年前。支持那个死气沉沉的操作系统总是一件痛苦的事,我不会再支持它了。是时候挥手告别了。这会让我成为一个“糟糕的Windows程序员吗?!”如果你还必须支持Win98,我很抱歉。。。真的很抱歉……你真的在推荐2017年的MFC和LPCTSTR吗-\与C++/CLI WinForms相比,它在VisualStudio中非常容易选择,并且可能是由未意识到
pin_ptr<const WCHAR> psName = PtrToStringChars (Name)
#include <msclr\marshal.h>

int main(array<System::String^>^ args)
{
    String^ managedStr = "I came from managed land!\r\n";

    // This controls the lifetime of the LPCTSTR that marshal_as returns. 
    // When this goes out of scope, the LPCTSTR will no longer be valid, 
    // so be aware of its lifetime.
    msclr::interop::marshal_context context;

    LPCTSTR unmanagedStr = context.marshal_as<LPCTSTR>(managedStr);

    OutputDebugString(unmanagedStr);

    return 0;
}
I came from managed land!