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.
