Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 3445
  • Last Modified:

using strcopy: cannot convert parameter 2 from 'const System::String __gc *' to 'const char *'


I am just learning OOP and C++.net.  I need to modify this code to make it
work.  Any help would be greatly appreciated!!!!!

// sends text to the controller, wait for response, return response
String * ODevice::SendAndGet( const String * Cmd ) const
   String * Response = "";

   if( hOms != NULL ) {          // if connected
      char resp[OMS_MAX_RESPONSE] = {'\0'}, cmd[OMS_MAX_RESPONSE] = {'\0'};
      strcpy( cmd, Cmd );        // dll takes only standard C types
      SendAndGetString( hOms, cmd, resp );
      Response->Format( "%s", resp );
   return( Response );

Here are the errors I receive:

test.cpp(74) : error C2664: 'strcpy' : cannot convert parameter 2 from 'const System::String __gc *' to 'const char *'  Cannot convert a managed type to an unmanaged type

test.cpp(76) : error C2664: 'System::String __gc *System::String::Format(System::String __gc *,System::Object __gc *)' : cannot convert parameter 2 from 'char [125]' to 'System::Object __gc *'  Cannot convert an unmanaged type to a managed type

This is at the top:

#using <mscorlib.dll>
using namespace System;

Here is the class definition for ODevice:

class ODevice  
     BYTE GetDone( void ) const;               // calls DLL function to get done flags
     void ClrDone( const BYTE );               // calls DLL function get clear done flags
     String * GetDrvrVrsn( void ) const;       // calls DLL function to get driver version
     String * SendAndGet( const String * ) const; // sends text to the controller and returns      controller's response
     void Disconnect( void );                  // disconnect from the controller
     void Connect( const String * );           // connect to the controller
     String * GetName( void ) const;           // returns the name of the current device

     ODevice();                                // standard constructor
     ~ODevice();                               // standard destructor

   HANDLE hOms;                                   // handle to the controller


Hopefully this is enough information.

Thanks in advance!

1 Solution
Kent OlsenData Warehouse Architect / DBACommented:
You're thinking in C. :)

Instead of strcpy(), just do:

cmd = Cmd;

These are classes and C++ will copy/convert the entire class object (struct) where C would not.

The same for the returned value:

Result = resp;

a System::String __gc * is a .net string object. It simply isn't the same as const char.

System::String class has a function that let you read the char string though and you can use that function to extract the string data.

I can't recall what exactly that function is but if you look up in your help (F1 key) you'll find it easily. Search on the namespace System and the class String and then look for member functions.

Note that in C# the string data type is the basic data type while in C++ it is a class object System::String.

Your second error is kinda the opposite you try to convert an unmanaged type (char []) to a managed type.

I am afraid that you have run into the problems that most C++ programmers run into when they try .net. .Net can handle C++ in that you can write C++ code to it but there are severals but's in this:

1. The code tend to be clobbered with __gc and other non-standard C++ things, so the code is really more .Net than it is C++.

2. You constantly run into that it really is trying to do two worlds in one program - the .Net world and the traditional C++ world and they do not really merge very well.

I will therefore recommend you to look into C# and rather use C# for .Net stuff and rather stick to traditional unmanaged code in C++ - preferably standard ANSI C++ code in C++ :-)

However, if you still want to use C++.Net you must understnad that it really is two different worlds. System::Object, System::String etc etc etc are all so-called managed structures. There's a garbage collector handling them and they won't mix very well with non-managed code. There are some basic functions that let you extract the const char * data from a string etc and you can use those to convert but it is always a conversion, just mindlessly attempting a strcpy won't work.

The System::String class is defined in .Net.

Another thing is that the string class is a string of wchar_t elements and not char elements. Asssuming your code has only plain ASCII characters you can easily convert the two, in the general case you should rather let it stay wchar_t and not attempt any conversion.

Here is how you can strcpy a System::String to a char string:

char * string_copy(char * dst, size_t sz,
                   System::String __gc * src)
   int len = src -> get_Length();
   if (len + 1 > sz)
      return 0; // not enough room.

   for (int i = 0; i < len; ++i) {
      wchar_t wc = src -> get_Chars(i);
      if (wc < 0 || wc > 127)
         return 0; // couldn't translate.
      dst[i] = char(wc);
   dst[len] = '\0';
   return dst;

If you want to make it a wchar_t string you can do this:

wchar_t * string_copy(wchar_t * dst, size_t sz,
                      System::String __gc * src)
   int len = src -> get_Length();
   if ((len + 1)*sizeof(wchar_t) > sz)
      return 0; // not enough room.
   for (int i = 0; i < len; ++i)
      dst[i] = src -> get_Chars(i);
   dst[len] = L'\0';
   return dst;

Similarly for the other way you have to create an object out of the string, you cannot just pass that string as argument to Format. I believe the compiler is already able to automatically translate a char to a System::String pointer - at least it doesn't complain about the first format string you provide. But translating a string to System::Object is obviously something it cannot do on its own. You must help the compiler by doing:

System::String * p = new System::String(resp,strlen(resp));

Here I assume that resp is a null terminated string, if it isn't you must do something else and provide the length through some other way than strlen above.

Now you can call:

Response -> Format( "...", p );

Of course, you could do it in one call by doing:

Response -> Format( "...", new System::String(resp,strlen(resp)));

Hope this is of help.


No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Answered: Points to Salte

Please leave any comments here within the next seven days. Experts: Silence
means you don't care.


-bcl (bcladd)
EE Cleanup Volunteer

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now