0

I wanna convert a System::String to char* as in order to open a file with fopen and then read it. I've tried with (char *)System::Convert::ToCharand it compiles fine but when I run the app it crashes. Here is the code:

    private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) //Convertir 
    {
        FILE * fichero = fopen((char*)Convert::ToChar(openFileDialog1->FileName), "r");
        if(fichero)
        {

But that crashes the app, so how can i fix it?

ScottJShea
  • 7,041
  • 11
  • 44
  • 67
user3145274
  • 33
  • 1
  • 7

1 Answers1

0

To get a string pointer usable by fopen(), you should use the marshal_as template function.

You can obtain a const char * thusly:

#include <msclr\marshal.h>
#include <msclr\marshal_cppstd.h>

    private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
    {
        std::string fileName = marshal_as<std::string>(openFileDialog1->FileName);
        FILE * fichero = fopen(fileName.c_str(), "r");
        if(fichero)
        {

However, do you really want to convert the string to narrow characters, therefore losing wide-character compatibility? No, you don't. You should actually use _wfopen, and marshal_as<std::wstring> (to get a wchar_t pointer) instead:

#include <wchar.h>
#include <msclr\marshal.h>
#include <msclr\marshal_cppstd.h>

    private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
    {
        std::wstring fileName = marshal_as<std::wstring>(openFileDialog1->FileName);
        FILE * fichero = _wfopen(fileName.c_str(), L"r");
        if(fichero)
        {

This is the correct code you should be using.


Note: To actually get a non-const char*, or if you only have Visual 2005, you should use Marshal::StringToHGlobalAnsi or Marshal::StringToHGlobalUni instead (don't forget the Marshal::FreeHGlobal when you're done with it) and cast the IntPtr into a char*/wchar_t* (probably via its ToPointer method).

Medinoc
  • 6,577
  • 20
  • 42
  • Indeed, .NET uses the Unicode character set and the Windows file system (NTFS) does, too. – Tom Blodget Dec 31 '13 at 00:03
  • No, don't use these functions in C++/CLI. Use the type-safe `marshal_as` template. See linked question http://stackoverflow.com/questions/6179451/c-cli-string-conversions – Ben Voigt Dec 31 '13 at 00:32
  • @BenVoigt Sorry, I forgot not everyone is constrained to VS2005. I edited my answer. – Medinoc Jan 01 '14 at 20:16
  • @Medinoc: Even in VS2005, `marshal_as` should be used. It's a pure header implementation, and can easily be dropped in. The `Marshal::StringToHGlobalAnsi` and friends really suck because the return value is not a valid `HGLOBAL`. – Ben Voigt Jan 01 '14 at 20:17
  • Oh yeah, the "GMEM_FIXED = pointer" problem. In fact, I even just ILDASM'd the method, and noticed it actually uses `LocalAlloc(LMEM_FIXED)`. – Medinoc Jan 01 '14 at 20:37