String のサンプル

このサンプルでは、アンマネージ関数から返された文字列の使用方法、および Unicode 形式または ANSI 形式の文字列を含む構造体の渡し方を示します。また、そのような文字列を適切に初期化する方法と、返された値を取得する方法も示します。

String のサンプルで使用するアンマネージ関数とその関数宣言を次に示します。

  • PinvokeLib.dll からエクスポートされる TestStringAsResult

    char* TestStringAsResult();
    
  • PinvokeLib.dll からエクスポートされる TestStringInStruct

    void TestStringInStruct(MYSTRSTRUCT* pStruct);
    
  • PinvokeLib.dll からエクスポートされる TestStringInStructAnsi

    void TestStringInStructAnsi(MYSTRSTRUCT2* pStruct);
    

PinvokeLib.dll はカスタム アンマネージ ライブラリであり、上記の関数および 2 つの構造体 MYSTRSTRUCT および MYSTRSTRUCT2 に関する実装を含んでいます。これらの構造体には次の要素が含まれます。

typedef struct _MYSTRSTRUCT
{
   wchar_t* buffer;
   UINT size; 
} MYSTRSTRUCT;
typedef struct _MYSTRSTRUCT2
{
   char* buffer;
   UINT size; 
} MYSTRSTRUCT2;

このサンプルでは、構造体の中で StringBuilder 型を使用できないため、マネージ構造体の MyStrStructMyStrStruct2 には StringBuilder バッファの代わりにマネージ文字列が含まれます。各メンバが出現する順番でメモリ内に順次配列されることを保証するために、StructLayoutAttribute 属性を設定します。ANSI 形式または Unicode 形式を指定するために、CharSet フィールドを設定します。

LibWrap クラスには、App クラスによって呼び出されるマネージ プロトタイプ メソッドが含まれます。通常、構造体は値渡しされますが、TestStringInStruct メソッドおよび TestStringInStructAnsi メソッドに対する引数にはキーワード ref (Visual Basic では ByRef) によるマークが付いているので、構造体は参照渡しされます。

次のコード例のソース コードは、.NET Framework「プラットフォーム呼び出しの技術サンプル」で提供されています。

プロトタイプの宣言

' Declares a managed structure for each unmanaged structure.
< StructLayout( LayoutKind.Sequential, CharSet:=CharSet.Unicode )> _
Public Structure MyStrStruct
   Public buffer As String
   Public size As Integer
End Structure 'MyStrStruct

< StructLayout( LayoutKind.Sequential, CharSet:=CharSet.Ansi )> _
Public Structure MyStrStruct2
   Public buffer As String
   Public size As Integer
End Structure 'MyStrStruct2

Public Class LibWrap
   ' Declares managed prototypes for unmanaged functions.
   Declare Function TestStringAsResult Lib "..\LIB\PinvokeLib.dll" () _
      As String
   Declare Sub TestStringInStruct Lib "..\LIB\PinvokeLib.dll" _
      ( ByRef mss As MyStrStruct )
   Declare Sub TestStringInStructAnsi Lib "..\LIB\PinvokeLib.dll" _
      ( ByRef mss As MyStrStruct2 )
End Class 'LibWrap
// Declares a managed structure for each unmanaged structure.
[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Unicode )]
public struct MyStrStruct 
{  
   public String buffer;
   public int size;
}
[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )]
public struct MyStrStruct2 
{  
   public String buffer;
   public int size;
}
public class LibWrap
{
   // Declares managed prototypes for unmanaged functions.
   [DllImport( "..\\LIB\\PinvokeLib.dll" )]
   public static extern String TestStringAsResult();

   [DllImport( "..\\LIB\\PinvokeLib.dll" )]
   public static extern void TestStringInStruct( ref MyStrStruct mss );

   [DllImport( "..\\LIB\\PinvokeLib.dll" )]
   public static extern void TestStringInStructAnsi( ref MyStrStruct2 
      mss );
}

関数の呼び出し

Public Class App
   Public Shared Sub Main()
      ' String as result.
      Dim strng As String = LibWrap.TestStringAsResult()
      Console.WriteLine( ControlChars.CrLf + "String returned: {0}", _
      strng )

      ' Initializes buffer and appends something to the end so the whole
      ' buffer is passed to the unmanaged side.
      Dim buffer As New StringBuilder( "content", 100 )
      buffer.Append( ChrW(0) )
      buffer.Append( "*"c, buffer.Capacity - 8)
      
      Dim mss As MyStrStruct
      mss.buffer = buffer.ToString()
      mss.size = mss.buffer.Length
      
      LibWrap.TestStringInStruct( mss )
      Console.WriteLine( ControlChars.CrLf + _
         "Buffer after Unicode function call: {0}", mss.buffer )

      Dim buffer2 As New StringBuilder( "content", 100 )
      buffer2.Append( ChrW(0) )
      buffer2.Append( "*"c, buffer2.Capacity - 8 )
      
      Dim mss2 As MyStrStruct2
      mss2.buffer = buffer2.ToString()
      mss2.size = mss2.buffer.Length 
      
      LibWrap.TestStringInStructAnsi( mss2 )
      Console.WriteLine( ControlChars.CrLf + _
         "Buffer after Ansi function call: {0}", mss2.buffer )
   End Sub 'Main
End Class 'App
public class App
{
   public static void Main()
   {
      // String as result.
      String str = LibWrap.TestStringAsResult();
      Console.WriteLine( "\nString returned: {0}", str );
      
      // Initializes buffer and appends something to the end so the whole
      // buffer is passed to the unmanaged side.
      StringBuilder buffer = new StringBuilder( "content", 100 ); 
      buffer.Append( (char)0 );
      buffer.Append( '*', buffer.Capacity - 8 );
      
      MyStrStruct mss;
      mss.buffer = buffer.ToString();
      mss.size = mss.buffer.Length;
      
      LibWrap.TestStringInStruct( ref mss );
      Console.WriteLine( "\nBuffer after Unicode function call: {0}", 
         mss.buffer );
      
      StringBuilder buffer2 = new StringBuilder( "content", 100 ); 
      buffer2.Append( (char)0 );
      buffer2.Append( '*', buffer2.Capacity - 8 );
      
      MyStrStruct2 mss2;
      mss2.buffer = buffer2.ToString();
      mss2.size = mss2.buffer.Length;
      
      LibWrap.TestStringInStructAnsi( ref mss2 );
      Console.WriteLine( "\nBuffer after Ansi function call: {0}", 
         mss2.buffer );
   }
}

参照

処理手順

プラットフォーム呼び出しの技術サンプル

概念

文字列のマーシャリング
プラットフォーム呼び出しのデータ型
文字列に対する既定のマーシャリング
マネージ コードでのプロトタイプの作成