SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Monoでのプログラミング実例集

MonoでP/Invokeを試してみたよ!

Monoでマネージコードからアンマネージ関数を呼び出す

  • X ポスト
  • このエントリーをはてなブックマークに追加

5.OpenCOBOLで作成したライブラリ内関数の呼び出し

概要

 呼び出し元から渡された文字列を、呼び出し先で少し編集を加えてコンソールに出力する単純なコンソールプログラムを作成します。

 呼び出し元コード(C#)として「PInvokeExample3.cs」、呼び出し先コード(COBOL)として「sub_wa4.cob」(「libsubcob.so」としてビルド)を使用します。

 呼び出し元(マネージ側)での扱いは、Cライブラリ内の関数を呼び出す際と同様と言えます。注意するのは、自作COBOLライブラリ内の関数(sub_wa4)を呼び出す前にCOBOLランタイム初期化関数(cob_init)を呼び出す必要があることです。

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); } }

 今回は、構造体を使用した文字列の受け渡しを行います。

呼び出し元(C#)
[StructLayout(LayoutKind.Sequential)]
public struct MyMsg
{
  public int cd;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst=51)]
  public string buffer;
}
呼び出し先(COBOL)
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#)

 「呼び出し元」として以下のコードを使用します。

PInvokeExample3.cs
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)

 「呼び出し先」として以下のコードを使用します。

sub_wa4.cob
***********************************************************
 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.

次のページ
6.まとめ

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Monoでのプログラミング実例集連載記事一覧
この記事の著者

sta(エステーエー)

風来坊blog:sta.blockhead

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/3460 2009/02/19 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング