#include <iostream>
#include "StringMarshaller.h"
int main()
{
using namespace std;
using namespace System;
String^ s1 = "sometimes ";
String^ s2 = "C++/CLI ";
String^ s3 = "sucks";
wcout << (const wchar_t*)StringMarshaller::MarshalStringUni(s1);
cout << StringMarshaller::MarshalStringAnsi(s2);
wcout << (const wchar_t*)StringMarshaller::MarshalStringPin(s3) << endl;
}
可以看到在StringMarshaller.h的名字空间StringMarshaller里有三个“函数”MarshalStringUni, MarshalStringAnsi和MarshalStringPin。其中前两个要将传递的内容进行一次拷贝,最后一个不拷贝,但是会在被调用函数返回之前pin住传递的System::String。MarshalStringPin得到的是unicode字串,因为CLR中的字串是以unicode方式储存的。需要注意的是使用这三个“函数”的条件是被调用函数不会保存传入的const char或const wchar_t指针,因为被调用函数返回后这些指针就失效了。#include "StringMarshaller.h"
int main()
{
using namespace std;
using namespace System;
String^ s1 = "sometimes ";
String^ s2 = "C++/CLI ";
String^ s3 = "sucks";
wcout << (const wchar_t*)StringMarshaller::MarshalStringUni(s1);
cout << StringMarshaller::MarshalStringAnsi(s2);
wcout << (const wchar_t*)StringMarshaller::MarshalStringPin(s3) << endl;
}
以下是StringMarshaller.h的源码:
#pragma once
#include <vcclr.h>
namespace StringMarshaller {
using namespace System;
using namespace System::Runtime::InteropServices;
/////////////////////////////////////////////////////////////////////
// The copying version
template<typename CharT> // CharT = char or unsigned char or wchar_t
class copy_marshaller
{
IntPtr m;
public:
copy_marshaller(IntPtr x) { m=x; }
operator const CharT*()
{ return static_cast<const CharT*>(m.ToPointer()); }
~copy_marshaller()
{ Marshal::FreeHGlobal(m); }
};
#define DEFINE_MarshalString(encoding, type)\
struct MarshalString##encoding: public copy_marshaller<type>\
{\
MarshalString##encoding(String^ s)\
: copy_marshaller<type>(Marshal::StringToHGlobal##encoding(s))\
{}\
};
DEFINE_MarshalString(Ansi, char) // MarshalStringAnsi
DEFINE_MarshalString(Uni, wchar_t) // MarshalStringUni
/////////////////////////////////////////////////////////////////////
// The pining version.
class MarshalStringPin
{
GCHandle h;
public:
MarshalStringPin(String^ s)
{
h = GCHandle::Alloc(s, GCHandleType::Pinned);
}
operator const wchar_t*()
{
return reinterpret_cast<wchar_t*>(
h.AddrOfPinnedObject().ToPointer());
}
~MarshalStringPin()
{
h.Free();
}
};
}
#include <vcclr.h>
namespace StringMarshaller {
using namespace System;
using namespace System::Runtime::InteropServices;
/////////////////////////////////////////////////////////////////////
// The copying version
template<typename CharT> // CharT = char or unsigned char or wchar_t
class copy_marshaller
{
IntPtr m;
public:
copy_marshaller(IntPtr x) { m=x; }
operator const CharT*()
{ return static_cast<const CharT*>(m.ToPointer()); }
~copy_marshaller()
{ Marshal::FreeHGlobal(m); }
};
#define DEFINE_MarshalString(encoding, type)\
struct MarshalString##encoding: public copy_marshaller<type>\
{\
MarshalString##encoding(String^ s)\
: copy_marshaller<type>(Marshal::StringToHGlobal##encoding(s))\
{}\
};
DEFINE_MarshalString(Ansi, char) // MarshalStringAnsi
DEFINE_MarshalString(Uni, wchar_t) // MarshalStringUni
/////////////////////////////////////////////////////////////////////
// The pining version.
class MarshalStringPin
{
GCHandle h;
public:
MarshalStringPin(String^ s)
{
h = GCHandle::Alloc(s, GCHandleType::Pinned);
}
operator const wchar_t*()
{
return reinterpret_cast<wchar_t*>(
h.AddrOfPinnedObject().ToPointer());
}
~MarshalStringPin()
{
h.Free();
}
};
}