5.OpenCOBOLで作成したライブラリ内関数の呼び出し
概要
呼び出し元から渡された文字列を、呼び出し先で少し編集を加えてコンソールに出力する単純なコンソールプログラムを作成します。
呼び出し元コード(C#)として「PInvokeExample3.cs」、呼び出し先コード(COBOL)として「sub_wa4.cob」(「libsubcob.so」としてビルド)を使用します。
呼び出し元(マネージ側)での扱いは、Cライブラリ内の関数を呼び出す際と同様と言えます。注意するのは、自作COBOLライブラリ内の関数(sub_wa4)を呼び出す前にCOBOLランタイム初期化関数(cob_init)を呼び出す必要があることです。
public class LibsubcobWrap { [DllImport("libcob")]
static extern void cob_init (int ac, string[] av); [DllImport("libsubcob")] static extern int sub_wa4(ref MyMsg iomsg); public static void sub_wa4ga(ref MyMsg iomsg) { cob_init(0, null); sub_wa4(ref iomsg); } }
今回は、構造体を使用した文字列の受け渡しを行います。
[StructLayout(LayoutKind.Sequential)] public struct MyMsg { public int cd; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=51)] public string buffer; }
LINKAGE SECTION. 01 iomsg. 03 mcd PIC S9(05) COMP-5. 03 buffer PIC X(51).
という対応になります。
作業する上でのディレクトリ構造は、下表のとおりとします。
C#コード格納先 | ~/src/cs/PInvokeExample |
COBOLコード格納先 | ~/src/cob |
自作ライブラリ格納先 | ~/lib |
作業用シェルスクリプト格納先 | ~/bin(環境変数「PATH」に設定済み) |
また、環境変数「LD_LIBRARY_PATH」の設定については、「4.自作Cライブラリ内関数の呼び出し」と同様とします。
呼び出し元(C#)
「呼び出し元」として以下のコードを使用します。
using System; using System.Runtime.InteropServices; namespace PInvokeExample { [StructLayout(LayoutKind.Sequential)] public struct MyMsg { public int cd; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=51)] public string buffer; } public class LibsubcobWrap { [DllImport("libcob")] static extern void cob_init (int ac, string[] av); [DllImport("libsubcob")] static extern int sub_wa4(ref MyMsg iomsg); public static void sub_wa4ga(ref MyMsg iomsg) { cob_init(0, null); sub_wa4(ref iomsg); } } public class Example3 { public static void Main(string[] args) { MyMsg iomsg; iomsg.cd = args.Length; iomsg.buffer = ""; if (args.Length == 1) { iomsg.buffer = args[0]; } LibsubcobWrap.sub_wa4ga(ref iomsg); Console.WriteLine("{0} 談", iomsg.buffer); } } } /* * ビルド: * * gmcs PInvokeExample3.cs * * 実行: * * mono PInvokeExample3.exe [何か] * */
呼び出し先(COBOL)
「呼び出し先」として以下のコードを使用します。
*********************************************************** IDENTIFICATION DIVISION. *********************************************************** PROGRAM-ID. sub_wa4. *********************************************************** ENVIRONMENT DIVISION. *********************************************************** DATA DIVISION. *********************************************************** WORKING-STORAGE SECTION. 01 wk-area. 03 wk-str1 PIC X(75) VALUE "". 03 wk-str2 PIC X(75) VALUE "". 03 wk-current-date. 05 wk-year PIC 9(04). 05 wk-month PIC 9(02). 05 wk-day PIC 9(02). 05 wk-hour PIC 9(02). 05 wk-min PIC 9(02). 05 wk-sec PIC 9(02). 05 wk-o PIC X(07). 03 wk-current-date-n. 05 wk-year PIC 9(04). 05 filler PIC X(03) VALUE "年". 05 wk-month PIC 9(02). 05 filler PIC X(03) VALUE "月". 05 wk-day PIC 9(02). 05 filler PIC X(03) VALUE "日". 05 wk-hour PIC 9(02). 05 filler PIC X(03) VALUE "時". 05 wk-min PIC 9(02). 05 filler PIC X(03) VALUE "分". 05 wk-sec PIC 9(02). 05 filler PIC X(03) VALUE "秒". 05 filler PIC X(01) VALUE low-value. * LINKAGE SECTION. 01 iomsg. 03 mcd PIC S9(05) COMP-5. 03 buffer PIC X(51). * *********************************************************** PROCEDURE DIVISION USING iomsg. *********************************************************** M-000. evaluate mcd of iomsg when 0 move "MonoはCOBOLで実装されとるよ" to wk-str1 when 1 string buffer of iomsg delimited by low-value "はわしが育てた" into wk-str1 when other move "MonoはCOBOLで実装されとる" to wk-str1 move "そんなふうに考えてた時期がわしにもあった" to wk-str2 end-evaluate. * display " ____". display " /__.))ノヽ". display " .|ミ.l _ ._ i.)". display " (^'ミ/.´・ .〈・ リ". display " .しi r、_) |". display " | `ニニ' / " wk-str1. display " ノ `ーーi " wk-str2. display "". * move function current-date to wk-current-date. move corr wk-current-date to wk-current-date-n. move wk-current-date-n to buffer of iomsg. * M-999. exit program.