Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

SmD

Problems marshalling C-Style strings to System::Strings in a managed environment

This topic is 5304 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I''ve been trying to marshal C-Style strings to System::String in a managed environment, but I was unable to do so. I''ve read a lot of documents on this subject during the last few days, and I''m currently able to marshal pointers, arrays, structures, and System::String to C-Style strings, but not the opposite!!! Here''s the code that I''m trying to use to marshal char array to String (It compiles but the System::String object returns random bits of data)
static int Function(int d, System::String __gc **buffer, long size)
{
  IntPtr ptr = Marshal::AllocCoTaskMem(size);
  int    ret = ::ibrd(d, (void *)ptr, size);

  System::String *temp = Marshal::PtrToStringAnsi(ptr);

  *buffer = temp;

  Marshal::FreeHGlobal(ptr);

  return ret;
}
I''ve also checked if ptr was bad, and it isn''t, so the problem lies in Marshal:trToStringAnsi(); Any help would be greatly appreciated...

Share this post


Link to post
Share on other sites
Advertisement
Why not simply use


char * cstr = "Hi, I''m a c-string!";
String * str = new String(cstr);


Regards,
Andre

Share this post


Link to post
Share on other sites
Thanks man!

I was unaware that one of the System::String constructors took a unsigned char *.

After all the countless hours I''ve spent reading documents on InteropServices, the solution to my problem was resolved with a simple constructor... GRRR!!!

Share this post


Link to post
Share on other sites
That string constructor expects UNICODE characters, though.

My StringHelper class has served me well(just disregard the pool stuff):


// $Id: StringHelper.h 879 2003-09-30 18:32:20Z Arild $

#pragma once
#include <vcclr.h>
#include <svn_utf.h>
#include "SvnClientException.h"
#include "Pool.h"
#include <apr_strings.h>

namespace NSvn
{
namespace Core
{
using namespace System;
using namespace System::Runtime::InteropServices;

// Helper class to effect string conversions

class StringHelper
{
public:
// <summary>constructor that takes a System::String</summary>

StringHelper( String __gc* string )
{
this->string = string;
this->charPtr = 0;
}

/// <summary>constructor that takes a const char*</summary>

StringHelper( const char* charPtr )
{
this->string = this->ConvertToSystemString( charPtr );
this->charPtr = 0;
}

/// <summary>implicit conversion to a System::String</summary>

operator String*() const
{
return this->string;
}

/// <summary>Copy constructor</summary>

StringHelper( const StringHelper& other )
{
//System::Strings can be shared

this->string = other.string;

//char ptrs can not

this->charPtr = 0;
}

/// <summary>Assignment operator</summary>

StringHelper& operator=( const StringHelper& other )
{
if ( this == &other )
return *this;

this->string = other.string;
if( this->charPtr != 0 )
this->FreeCharPtr( this->charPtr );

this->charPtr = 0;

return *this;
}

/// <summary>Copies the string to the pool, encoded as UTF8</summary>

char* CopyToPoolUtf8( apr_pool_t* pool )
{
const char* utf8String;
HandleError( svn_utf_cstring_to_utf8( &utf8String, this->CopyToPool( pool ),
pool ) );

return const_cast<char*>(utf8String);
}

char* CopyToPool( apr_pool_t* pool )
{
//TODO: unicode issues


char* hglobal = this->ConvertToCharPtr( this->string );

//make room in the pool and copy our string there

char* ptr = apr_pstrdup( pool, hglobal );

// free the hglobal

this->FreeCharPtr( hglobal );

return ptr;
}



/// <summary>implicit conversion to a const char*</summary>

operator const char* () const
{
// lazy creation of the char* - we might not need it

if ( this->charPtr == 0 )
this->charPtr = this->ConvertToCharPtr( this->string );

return this->charPtr;
}

// <summary>dtor - get rid of the char ptr</summary>

~StringHelper()
{
if ( this->charPtr != 0 )
this->FreeCharPtr( this->charPtr );
}

private:
/// <summary>convert a char ptr to a System::String</summary>

String __gc* ConvertToSystemString( const char* ptr )
{
return Marshal::PtrToStringAnsi( static_cast<IntPtr>(const_cast<char*>(ptr) ) );
}

/// <summary>convert a System::String to a char*</summary>

char* ConvertToCharPtr( String __gc* string ) const
{
return static_cast<char*>( Marshal::StringToHGlobalAnsi( string ).ToPointer() );
}

/// <summary>free the memory allocated by the StringToHGlobalAnsi call</summary>

void FreeCharPtr( char* ptr )
{
Marshal::FreeHGlobal( static_cast<IntPtr>( static_cast<void*>(ptr) ) );
}

gcroot<String*> string;
mutable char* charPtr;
};
}
}

Usually I just use it function-style, whenever I need to convert from one of the other: String* someString = S"Moo"; some_c_api( StringHelper(someString) ); or char* ptr = "Foo"; obj->Method( StringHelper(ptr) );. The conversion operators do most of the job.


--
AnkhSVN - A Visual Studio .NET Addin for the Subversion version control system.
[Project site] [Blog] [RSS] [Browse the source] [IRC channel]

Share this post


Link to post
Share on other sites
quote:
Original post by Arild Fines
That string constructor expects UNICODE characters, though.


No, it doesn't. It works with usual ANSI c-strings (0-terminated).

http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemStringClassctorTopic3.asp


I compiled it and it works. Of course, there *are* c'tors that expect UNICODE. However, that special one I mentioned does not.

Regards,
Andre

[edited by - VizOne on February 6, 2004 12:49:24 PM]

Share this post


Link to post
Share on other sites
Weird. My local MSDN(April 2003) says "Initializes a new instance of the String class to the value indicated by a specified pointer to an array of Unicode characters."

Share this post


Link to post
Share on other sites
quote:
Original post by Arild Fines
Weird. My local MSDN(April 2003) says "Initializes a new instance of the String class to the value indicated by a specified pointer to an array of Unicode characters."


Let me guess: you have the language filter set to C#? In C#, a char* of course is a UNICODE string. But there is a String(sbyte*) construktor which translates to ("real" 8bit) char* in C++. In C++ the original c#-char* constructor parametertype translates to wchar_t *.

Weird, isn''t it? :D

Regards,
Andre

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!