構造体

Similar documents
構造体

ファイル操作-インターネットキャッシュ

プロセス間通信

ウィンドウ操作 応用

ファイル操作

ICONファイルフォーマット

NotifyIconコントロール

グラフィックス

Visual Basic 資料 電脳梁山泊烏賊塾 コレクション初期化子 コレクション初期化子 初めに.NET 版の Visual Basic では 其れ迄の Visual Basic 6.0 とは異なり 下記の例の様に変数宣言の構文に 初期値を代入する式が書ける様に成った 其の際 1 の様に単一の値

Userコントロール

Microsoft Word - DT-5100Lib_Manual_DotNet.doc

データアダプタ概要

プラグイン

ハッシュテーブル

VB 資料 電脳梁山泊烏賊塾 音声認識 System.Speech の利用 System.Speech に依るディクテーション ( 音声を文字列化 ).NetFramework3.0 以上 (Visual Studio 2010 以降 ) では 標準で System.Speech が用意されて居るの

ファイル操作-バイナリファイル

VB.NET解説

DAOの利用

ファイル監視

ListViewコントロール

ルーレットプログラム

第 2 章インタフェース定義言語 (IDL) IDL とは 言語や OS に依存しないインタフェース定義を行うためのインタフェース定義言語です CORBA アプリケーションを作成する場合は インタフェースを定義した IDL ファイルを作成する必要があります ここでは IDL の文法や IDL ファイ

VB6互換のファイルの処理

Microsoft Word _VBAProg1.docx

API 連携方式 外部 DLL の呼び出し宣言 外部 DLL の呼び出し宣言のサンプルコード (Microsoft Visual C#.NET の場合 ) プログラムコードの先頭で using System.Runtime.InteropServices; が必要 クラスの内部に以下のような外部 D

正規表現応用

VB実用⑦ エクセル操作Ⅰ

LogisticaTRUCKServer-Ⅱ距離計算サーバ/Active-Xコントロール/クライアント 概略   

Microsoft Excel操作


.NETプログラマー早期育成ドリル ~VB編 付録 文法早見表~

mySQLの利用

VFD256 サンプルプログラム

Agenda Windows 64-bit 概要マネージコード開発 ( 導入 ) マネージコード開発 ( 詳細 ) コーディング上の留意点まとめ

正規表現詳細

グラフィックス 目次

スレッド操作 タイマー

ブロック パニック

回文作成支援プログラム

Java知識テスト問題

64bit環境で32bitコンポーネントの利用

GS1-128 の描画 DLL について (ver. 2.3) 動作環境など動作環境 WindowsXP Windows Vista Windows7 Windows8/8.1 Windows10 上記 OS について すべて日本語版を対象としております 32bit アプリケーションから呼び出される

JavaプログラミングⅠ

コードページ

平成 30 年度 プログラミング研修講座 岩手県立総合教育センター

VB実用Ⅲ⑩ フリーデータベースⅡ

占領双六ゲーム

エクセル詳細 アドイン

C 資料 電脳梁山泊烏賊塾 構造体 C++ の構造体 初めに 此処では Visual Studio 2017 を起動し 新しいプロジェクトで Visual C++ の Windows デスクトップを選択し Windows コンソールアプリケーションを作成する 定義と変数宣言 C++ に

Prog2_12th

LogisticaTRUCKServer-Ⅱ距離計算サーバ/Active-Xコントロール/クライアント 概略   

PYTHON 資料 電脳梁山泊烏賊塾 PYTHON 入門 文字列 文字列リテラル プログラムの中で文字列を表す方法は幾つか有るが 基本的な方法は下記の 2 種で有る 対象と成る文字の集まりをダブルクオーテーション ( " ) で囲うか シングルクオーテーション ( ' ) で囲う PYTHON3 "

アプリケーション

モグラ叩きプログラム

sinfI2005_VBA.doc

PowerPoint プレゼンテーション

印刷

インベーダープログラム

回文作成支援プログラム


C 資料 電脳梁山泊烏賊塾 キャスト C++ のキャスト 初めに 此処では Visual Studio 2017 を起動し 新しいプロジェクトで Visual C++ の Windows デスクトップを選択し Windows コンソールアプリケーションを作成する C++ でのキャスト

MISAO with WPF

3軸加速度センサーモジュール MM-2860 書込み済みマイコンプログラム通信コマンド概要

ICONファイルフォーマット

プログラミング基礎I(再)

VB.NET解説

データベースプログラミング

プリンタ印字用 DLL 取扱説明書

intra-mart Accel Platform — IM-Repository拡張プログラミングガイド   初版  

AquesTalk for WinCE プログラミングガイド

チャットプログラム

画像閲覧プログラム

Java Scriptプログラミング入門 3.6~ 茨城大学工学部情報工学科 08T4018Y 小幡智裕

GUIプログラムⅣ

Java プログラミング Ⅰ 3 回目変数 変数 変 数 一時的に値を記憶させておく機能型 ( データ型 ) と識別子をもつ 2 型 ( データ型 ) 変数の種類型に応じて記憶できる値の種類や範囲が決まる 型 値の種類 値の範囲 boolean 真偽値 true / false char 2バイト文

ウィンドウ操作 詳細

PowerPoint プレゼンテーション

Microsoft PowerPoint - ruby_instruction.ppt

VB実用③ アクセス操作Ⅰ

CashDrawer ライブラリ API 仕様書 2014/07/09 CashDrawer ライブラリ API 仕様書 Rev / 10

WebBrowserコントロール

JavaプログラミングⅠ

C 資料 電脳梁山泊烏賊塾 ファイルの入出力 C++ のバイナリファイル入出力 初めに 此処では Visual Studio 2017 を起動し 新しいプロジェクトで Visual C++ の Windows デスクトップを選択し Windows コンソールアプリケーションを作成する

Java講座

RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用

PYTHON 資料 電脳梁山泊烏賊塾 PYTHON 入門 関数とメソッド 関数とメソッド Python には関数 (function) とメソッド (method) が有る モジュール内に def で定義されて居る物が関数 クラス内に def で定義されて居る物がメソッドに成る ( 正確にはクラスが

メール送信

ブロック崩し風テニス

Case 0 sqlcmdi.parameters("?tencode").value = Iidata(0) sqlcmdi.parameters("?tenname").value = Iidata(1) 内容を追加します sqlcmdi.executenonquery() Case Else

データベースⅠ

開発・運用時のガイド JDK8への移行に伴う留意点 [UNIX]

Microsoft Word - Android_SQLite講座_画面800×1280

グラフィックス 目次

キーボードAPI関数

VB実用⑪ 印刷Ⅰ(プリンタ設定)

デジタル表現論・第6回

チャットプログラム

(1) プログラムの開始場所はいつでも main( ) メソッドから始まる 順番に実行され add( a,b) が実行される これは メソッドを呼び出す ともいう (2)add( ) メソッドに実行が移る この際 add( ) メソッド呼び出し時の a と b の値がそれぞれ add( ) メソッド

MS Office オートメーション

グラフィックトレーニング 概要.NET のグラフィック描画は どんなことができるのでしょうか? グラフィックオブジェクトやグラフィック環境 概念を理解するためには クラスを使って馴れることが近道です 本 書に記載されているコードをカットアンドペーストして 一つ一つの機能を体験してください 前提 グラ

Transcription:

構造体 構造体を取り扱うには System.Runtime.InteropServices 名前空間をインポートして置くと便利で有る Imports System.Runtime.InteropServices using System.Runtime.InteropServices; C# ユーザー定義型 (Type) と構造体 (Structure) 6.0 のユーザー定義型 (Type) を.NET 以降の構造体 (Structure) に移行する時に問題に成るのが 配列と固定長文字列の要素で有る Private Type MyType ItemArray(5) As Integer ItemString As String * 100 End Type 6.0 上記のユーザー定義型をアップグレードすると 下記の様な構造体に成る Private Structure MyType Dim ItemArray() As Short <VBFixedString(100), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=100)> Dim ItemString As String Public Sub Initialize() ReDim ItemArray(5) End Sub End Structure 此の構造体には 配列の要素数を初期化する為のユーザー定義関数 (Initialize) が含まれて居り 此の関数を利用して配列の要素を初期化するように TODO コメントも追加されるので 此のコメントを参考に 配列の要素数を初期化する 亦 固定長文字列に付いては 可変長文字列に変更されるが 固定配列やマーシャリングの為の属性が追加されて居るので 固定長文字列の様に利用する事が出来る の文字列は 既定では可変長で有る 固定長文字列を必要とする のファイル入出力関数 (FileGet や FilePut 等 ) を使う時には VBFixedStringAttribute 属性を使用する 此の属性は 此等の関数への情報提供の為の属性で 可変長の文字列を固定長の文字列に変換する為には使用出来ない 従って 此の属性に依って文字列自身の実際の長さが変更される事は無い点に注意を要する -1-

System.Runtime.InteropServices.StructLayout 属性 System.Runtime.InteropServices.StructLayout 属性を使用すると 構造体のメモリ内での配置をカスタマイズする事が出来る 例えば StructLayout(LayoutKind.Explicit) 属性と FieldOffset 属性を使用すると C/C++ の共用体と呼ばれる物を作成する事が出来る 下記のコードセグメントでは 構造体 Test1 の総ての要素 ( フィールド ) がメモリ内の同じ場所で開始される <StructLayout(LayoutKind.Explicit)> _ Private Structure Test1 <FieldOffset(0)> Dim I As Integer <FieldOffset(0)> Dim D As Double <FieldOffset(0)> Dim C As Char <FieldOffset(0)> Dim B As Byte End Structure [StructLayout(LayoutKind.Explicit)] private struct Test1 public int i; public double d; public char c; public byte b; } C# 0 1 2 3 4 5 6 7 int i double d char c byte b 要素 ( フィールド ) が別の明示的に設定された場所から開始される別の例を下記に示す <StructLayout(LayoutKind.Explicit)> _ Private Structure Test2 <FieldOffset(0)> Dim L As Long <FieldOffset(0)> Dim I1 As Integer <FieldOffset(4)> Dim I2 As Integer <FieldOffset(8)> Dim D As Double <FieldOffset(12)> Dim C As Char <FieldOffset(14)> Dim B As Byte End Structure -2-

[StructLayout(LayoutKind.Explicit)] private struct Test2 public long l; public int i1; [FieldOffset(4)] public int i2; [FieldOffset(8)] public double d; [FieldOffset(12)] public char c; [FieldOffset(14)] public byte b; } C# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 long l double d int i1 int i2 char c byte b 2 個の int 要素の i1 と i2 は long 要素の l と同じメモリ位置を共有する 此の様な構造体レイアウトの制御は プラットフォーム呼出の時に便利で有る LayoutKind 列挙型 Auto Explicit Sequential ランタイムは アンマネージメモリ内のオブジェクトのメンバに対して適切なレイアウトを自動的に選択する 此の列挙体メンバで定義されたオブジェクトは マネージコードの外に公開出来ない 公開しようとすると 例外が生成される アンマネージメモリ内に有るオブジェクトの各メンバの正確な位置は 明示的に制御される 各メンバは FieldOffsetAttribute 属性を使用して 其の型内のフィールドの位置を指定する必要が有る オブジェクトのメンバは アンマネージメモリにエクスポートする時に表示される順番に従ってレイアウトされる メンバは StructLayoutAttribute.Pack で指定したパッキングに従ってレイアウトされる メンバは非連続する事が出来る <StructLayout(LayoutKind.Sequential)> _ Public Structure Point Public x As Integer Public y As Integer End Structure 'Point <StructLayout(LayoutKind.Explicit)> _ Public Structure Rect <FieldOffset(0)> Public left As Integer -3-

<FieldOffset(4)> Public top As Integer <FieldOffset(8)> Public right As Integer <FieldOffset(12)> Public bottom As Integer End Structure 'Rect [StructLayout(LayoutKind.Sequential)] public struct Point public int x; public int y; } [StructLayout(LayoutKind.Explicit)] public struct Rect public int left; [FieldOffset(4)] public int top; [FieldOffset(8)] public int right; [FieldOffset(12)] public int bottom; } [StructLayout(LayoutKind::Sequential)] value struct Point public: int x; int y; }; C# C++ [StructLayout(LayoutKind::Explicit)] value struct Rect public: int left; [FieldOffset(4)] int top; [FieldOffset(8)] int right; [FieldOffset(12)] int bottom; }; -4-

MarshalAsAttribute クラス Marshal とは プログラミング用語では 或るプログラムで利用されるデータ形式を 異なるプログラムで利用可能な形式に変換する事を謂い 此のクラスは マネージコードとアンマネージコードとの間のデータのマーシャリング方法を示す メンバー名 AnsiBStr AsAny Bool BStr ByValArray ByValTStr Currency CustomMar shaler Error FunctionPtr HString I1 I2 I4 I8 説明長さを示すプレフィックスを付けた &1; バイトの ANSI 文字列 此のメンバーは String データ型で使用出来る 実行時にオブジェクトの型を確認し 其の型としてオブジェクトをマーシャリングする動的な型 此のメンバーは プラットフォーム呼出メソッドに而巳有効で有る 4 バイトの Boolean 値 (true!= 0 false = 0) 此れは Win32 BOOL 型で有る 長さを示すプリフィックスを付けた &2; バイトのUnicode 文字列 此のメンバー (COM の既定の文字列 ) は String データ型で使用出来る MarshalAsAttribute.Value プロパティを ByValArray に設定した場合 SizeConst フィールドは 配列の要素数を示す様に設定する必要が有る ArraySubType フィールドには 文字列型を区別する必要が有る場合に オプションとして配列要素の UnmanagedType を格納出来る 此の UnmanagedType は 要素が構造体にフィールドとして定義されて居る配列で而巳使用出来る 構造体に定義されて居るインライン固定長文字配列で使用する ByValTStr で使用する文字型は 格納される構造体に適用する System.Runtime.InteropServices. StructLayoutAttribute 属性の引数 System.Runtime.InteropServices.CharSet に依って決定される 配列のサイズを示す場合は 常に MarshalAsAttribute.SizeConst フィールドを使用する 通貨型 10 進値を Decimal ではなく COM 通貨型としてマーシャリングする為に System.Decimal で使用する MarshalAsAttribute.MarshalType 又は MarshalAsAttribute.MarshalTypeRef フィールドと共に使用する場合に カスタムマーシャラークラスを指定する MarshalAsAttribute.MarshalCookie フィールドは カスタムマーシャラーに追加の情報を渡す為に使用出来る 此のメンバーは任意の参照型で使用出来る I4 又は U4 に関連付けられたネイティブな型 此の型に依り パラメーターはエクスポート先のタイプライブラリに HRESULT としてエクスポートされる C スタイルの関数ポインターとして使用出来る整数値 此のメンバーは Delegate データ型又は Delegate から継承した型で使用出来る Windows ランタイム文字列 此のメンバーは System.String データ型で使用出来る 1 バイト符号付き整数 此のメンバーを使用すると Boolean 値を 1 バイトの C スタイル bool(true = 1 false = 0) に変換出来る 2 バイト符号付き整数 4 バイト符号付き整数 8 バイト符号付き整数 IDispatch COM の IDispatch ポインター (Microsoft 6.0 では Object) IInspectable Windows ランタイムインターフェイスポインター 此のメンバーは Object データ型で使用出来る Interface COM インターフェイスポインター インターフェイスの Guid は クラスメタデータから取得する インターフェイス型を直接指定する場合 又は クラスに適用する場合は既定のインターフェイス型を指定する場合に 此のメンバーを使用する 此のメンバーは Object データ型に適用すると UnmanagedType.IUnknown と同じ動作を -5-

生成する IUnknown COM IUnknown ポインター 此のメンバーは Object データ型で使用出来る LPArray C スタイル配列の最初の要素へのポインター マネージコードからアンマネージコードにマーシャリングする場合 配列長はマネージ配列長に依って決定される アンマネージコードからマネージコードにマーシャリングする場合 配列の長さは MarshalAsAttribute.SizeConst フィールドと MarshalAsAttribute.SizeParamIndex フィールドに依って決まる 文字列の型を区別する必要が有る場合は 配列内の要素のアンマネージ型も考慮される LPStr 終端が null の &1; バイトの ANSI 文字列 此のメンバーは System.String データ型及び System.Text.StringBuilder データ型で使用出来る LPStruct マネージ書式指定クラスをマーシャリングする時に使用する C スタイル構造体へのポインター 此のメンバーは プラットフォーム呼出メソッドに而巳有効で有る LPTStr プラットフォームに依存する文字列 Windows 98 では ANSI Windows NT と Windows XP では Unicode 型 LPTStr の文字列のエクスポートがサポートされて居ない為 此の値は COM 相互運用ではサポートされず プラットフォーム呼出而巳でサポートされる LPUTF8Str UTF-8 でエンコードされた文字列へのポインター LPWStr 終端が null の 2 バイトの Unicode 文字列 R4 4 バイト浮動小数点数 R8 8 バイトの浮動小数点数 SafeArray SafeArray は 関連付けられた配列データの型 ランク 及び 境界を格納する自己記述型の配列で有る MarshalAsAttribute.SafeArraySubType フィールドと併せて此のメンバーを使用する事に依って 既定の要素の型をオーバーライド出来る Struct マネージ書式指定クラスと値型をマーシャリングする為に使用する VARIANT SysInt プラットフォーム依存 符号付き整数 :32 ビット Windows では 4 バイト 64 ビット Windows では 8 バイト SysUInt プラットフォーム依存 符号無し整数 :32 ビット Windows では 4 バイト 64 ビット Windows では 8 バイト TBStr 長さを示すプレフィックスを付けた プラットフォームに依存する char 文字列 Windows 98 では ANSI Windows NT では Unicode 此の BSTR に似たメンバーを使用する事は殆ど無い U1 1 バイト符号無し整数 U2 2 バイト符号無し整数 U4 4 バイト符号無し整数 U8 8 バイト符号無し整数 VariantBool 2 バイトの OLE 定義 VARIANT_BOOL 型 (true = -1 false = 0) VBByRefStr で アンマネージコードの文字列を変更し 結果をマネージコードに反映出来る様にする値 此の値は プラットフォーム呼び出しで而巳サポートされる Declare 文の引数型を変換する MarshalAs 属性.NET 以降では.NET Framework の幅広いクラスライブラリにアクセス出来る為 Visual Basic 6.0 と異なり Win32 API を呼び出す Declare 文を使用する機会は減少したのではないかと思う しかし Win32 API を呼び出す機会がゼロに成った訳ではなく 依然として Declare 文は存在して居る 此の時 問題に成るのが 文字列等のデータ型が.NET 以降と Win32 API で互換性が全く無い事で有る.NET 以降の文字列は System.String クラスの文字列クラスに依り表現さ -6-

れるが Win32 API では文字型の配列として表現される 此の相違を乗り越えるには API 呼び出し時に適切なデータ型の変換が必要と成る 此の時の変換方法を指定する手段として MarshalAs 属性が使用される 以下は 実際に MarshalAs 属性を使用したサンプルプログラムで有る 1 Imports System.Runtime.InteropServices 2 3 Public Class Form1 4 Inherits System.Windows.Forms.Form 5 6 Windows フォームデザイナで生成されたコード 7 8 Declare Auto Sub MessageBox Lib "user32.dll" ( _ 9 ByVal hwnd As Integer, _ 10 <MarshalAs(UnmanagedType.LPTStr)> ByVal lptext As String, _ 11 <MarshalAs(UnmanagedType.LPTStr)> ByVal lpcaption As String, _ 12 ByVal utype As Integer) 13 14 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles MyBase.Load 15 MessageBox(0, "Hello!", "Sample Program", 0) 16 End Sub 17 End Class 此処で注目す可き点は 8~12 行目の Declare 文の中で使用されて居る MarshalAs 属性で有る 10 行目と 11 行目の文字列は 其の儘 Win32 API に渡す事が出来ないので 変換する必要が有る 其処で MarshalAs 属性は其の必要性を指定して居る 具体的に何んなデータ型に変換するかは UnmanagedType 列挙型の値で指定して居る MarshalAs 属性と UnmanagedType 列挙型は System.Runtime.InteropServices 名前空間に属して居るので 1 行目の Imports 文で此の名前空間を指定して居る 扨て Win32 API 呼び出し時の文字列に関する今一つの問題は Win32 API には文字コードの相違に依って同じ機能を持った API が実際には 2 つ存在して居る場合が有る事だ 詰り 其の 2 つの孰れを呼び出すかの明示的な指定と 孰れの文字コードを指定して引数を変換させるかと謂う指定が必要とされる 上記のサンプルプログラムの場合 Declare キーワードの次の Auto キーワードが OS の種類に応じて 自動的に 2 つの Win32 API の中から選択する事を指定して居る Windows 9X 系では ANSI 系を Windows NT 系では Unicode 系の API が呼ばれる事に成ると思う 引数の変換に指定した UnmanagedType.LPTStr と謂う値は 状況に応じて適切な文字コードを選択すると謂う機能を持つ 併し 自動判定に頼らず 明示的に指定する事も出来る 以下は 明示的に Unicode 系の Win32 API を選ぶ様に記述したソースで有る 1 Imports System.Runtime.InteropServices 2 3 Public Class Form1 4 Inherits System.Windows.Forms.Form 5 6 Windows フォームデザイナで生成されたコード 7-7-

8 Declare Auto Sub MessageBoxW Lib "user32.dll" ( _ 9 ByVal hwnd As Integer, _ 10 <MarshalAs(UnmanagedType.LPWStr)> ByVal lptext As String, _ 11 <MarshalAs(UnmanagedType.LPWStr)> ByVal lpcaption As String, _ 12 ByVal utype As Integer) 13 14 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles MyBase.Load 15 MessageBoxW(0, "Hello!", "Sample Program", 0) 16 End Sub 17 End Class ソースコードの変更点は 2 つ有る 1 つは 8 行目のメソッド名を MessageBox から MessageBoxW に変更し Unicode 系の MessageBox API の本当の名前を指定した事だ 今 1 つは 10~11 行目の MarshalAs 属性で Unicode 文字列を意味する UnmanagedType.LPWStr と謂う値を指定した事で有る 猶 謂う迄も無く メソッドの名前は Declare 文の Alias キーワードを活用すれば変更可能なので MessageBox と謂う名前で呼び出す様にも出来る 逆に ANSI 系 ( 日本ではシフト JIS) を用いて文字列を受け渡す様に変更したサンプルプログラムを下記に示す 1 Imports System.Runtime.InteropServices 2 3 Public Class Form1 4 Inherits System.Windows.Forms.Form 5 6 Windows フォームデザイナで生成されたコード 7 8 Declare Auto Sub MessageBoxA Lib "user32.dll" ( _ 9 ByVal hwnd As Integer, _ 10 <MarshalAs(UnmanagedType.LPStr)> ByVal lptext As String, _ 11 <MarshalAs(UnmanagedType.LPStr)> ByVal lpcaption As String, _ 12 ByVal utype As Integer) 13 14 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles MyBase.Load 15 MessageBoxA(0, "Hello!", "Sample Program", 0) 16 End Sub 17 End Class 此処では Win32 API の名前は ANSI 系の Win32 API としての本名で有る MessageBoxA に変更し 変換するデータ型を UnmanagedType.LPStr として居る UnmanagedType.LPStr は ANSI 系の文字列を示す値で有る -8-