• ベストアンサー

string型とsbyte*型の変換

現在、C++で作成したクラスを、 C#から呼び出し実行しようとしております。 C++側での引数のデータ型は、「char *」 、 C#側での引数は、「sbyte*」となっています。 このクラスに対し、C#側から文字列をC++側に渡したい場合、 string型からsbyte*型へ変換しなければならないと 考えているのですが、その方法がわかりません。 そもそもの考え方が正しいのかどうかもわからない状態ですので、 質問そのものがとんちんかんなことを聞いているのかも知れませんが、 どうぞよろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • sygh
  • ベストアンサー率76% (42/55)
回答No.1

「C++」というのは「C++/CLI」のことですか? 処理系がVC 2005以降だと仮定して話を進めます。 例えば下記のようなC++/CLIの参照クラスを含むクラス ライブラリ プロジェクト「CppCliString」があったとして、 // CppCliString.h #pragma once #include <cstdio> #include <locale.h> #include <vcclr.h> // http://support.microsoft.com/kb/311259/ja using namespace System; using namespace System::Runtime::InteropServices; namespace CppCliString { public ref class Class1 { public: static void SetLocaleW() { _wsetlocale(LC_ALL, L""); } static void PutsA(char* pStr) { puts(__FUNCTION__ "(), Ansi Version:"); puts(pStr); } static void PutsW(wchar_t* pStr) { _putws(__FUNCTIONW__ L"(), Unicode Version:"); _putws(pStr); } static void WriteLineA(String^ hStr) { puts(__FUNCTION__ "(), Ansi Version:"); // ディープ コピー発生。 IntPtr ptr = Marshal::StringToHGlobalAnsi(hStr); puts((char*)(void*)ptr); Marshal::FreeHGlobal(ptr); } static void WriteLineW(String^ hStr) { _putws(__FUNCTIONW__ L"(), Unicode Version:"); // ディープ コピー発生。 IntPtr ptr = Marshal::StringToHGlobalUni(hStr); _putws((wchar_t*)(void*)ptr); Marshal::FreeHGlobal(ptr); } }; } C#側は下記。 // Program.cs using System; using System.Runtime.InteropServices; namespace CsStringTest { class Program { static void Main(string[] args) { Console.WriteLine("Managed/Unmanaged String Test"); string strText = "hoge文字列ソースhoge"; CppCliString.Class1.SetLocaleW(); // unsafe ステートメントはお勧めしません。 unsafe { fixed (char* pStr = strText) { // コピーは発生しない。 CppCliString.Class1.PutsW(pStr); } { // ディープ コピー発生。 IntPtr ptr = Marshal.StringToHGlobalUni(strText); CppCliString.Class1.PutsW((char*)ptr); Marshal.FreeHGlobal(ptr); } { // ディープ コピー発生。 IntPtr ptr = Marshal.StringToHGlobalAnsi(strText); CppCliString.Class1.PutsA((sbyte*)ptr); Marshal.FreeHGlobal(ptr); } } // こちらを推奨。というかそのために C++/CLI が存在する。 CppCliString.Class1.WriteLineW(strText); CppCliString.Class1.WriteLineA(strText); Console.WriteLine("Press any..."); Console.ReadKey(true); } } } C#側のプロジェクト プロパティで「アンセーフ コードの許可」にチェックを入れて、 C++/CLI側のターゲットがWin32の場合、C#側もターゲットをx86にする。 でも、C#でunsafeとかポインタを使うのはやめたほうがいいです。