2026/08/08

サポート対象外?

JV-Link Versioin 5.0.0 64bitは、まあ、これまでのJV-Linkと大差ないものって認識をしてみました。当初、まだVisual Studio 2019だった頃、確かにプロジェクトで.NET Frameworkを選択する必要がありました。これ、Visual Studio 2019がまだ32bitだったりしたのでそれで使えばActiveXとかの関係からかツールボックスにJV-Linkが表示されてフォームに貼り付けて利用できた。Visual Studio 2022から64bit化され一時は使えないって感じだったけど、こちらもプロジェクトの参照にJV-Linkを追加して設定を変えて、フォームへの貼付ではなく、単にクラスを宣言する方法にする事で利用可能でした。

もしかして、今回のバージョンもそうなのでは?って事で昨晩試しました。

「次へ」

プロジェクト名は何でもいいけど「次へ」

このままでも良いけど、さらだは.NET 9でないとダメですが「作成」

開いた状態だとこんな感じになってますが、[プロジェクト(P)]-[COM 参照の追加(C)...]で

"JRA-VAN Data Lab. 1.1.8タイプ ライブラリ"左にチェック入れて「OK」すると

依存関係にCOMが追加され展開すると

Interop.JVDTLabLibがあり、それをクリックして

プロパティ見ると「相互運用型の埋め込み」が「はい」になっているので「いいえ」に変更し、

あとは、この使い方ではフォームにJVLink Classを貼り付けようとしてもツールボックスには表示されませんのでフォームのコードでクラス宣言し、プラットフォームをx64にすれば使えますね。

namespace JVLink64Test;

public partial class Form1 : Form
{
    JVDTLabLib.JVLink clsJVLink = new JVDTLabLib.JVLink();
    public Form1()
    {
        InitializeComponent();
    }
}

プラットフォームの追加変更はJRA-VANでも詳しく載ってますので割合します。フォームにメニューを追加して

「JV-Linkの設定(J)...」メニューのイベントに

    private void mnuSettingJVLink_Click(object sender, EventArgs e)
    {
        try
        {
            int iReturnCode = clsJVLink.JVSetUIProperties();
            if (iReturnCode != 0)
            {
                MessageBox.Show(String.Format("エラーコード:{0}", iReturnCode), "JVSetUIProperties", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "JVSetUIProperties", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

って感じにすれば、実行すると

普通に起動して、メニューから[設定(C)]-[JV-Linkの設定(J)...]とすれば

下の方を見るとしっかり"JVLink Version : 5.0.0 (64bit版)"となっているのが見れます。

まあ、これはそれ程苦労せずに分かったのですが、問題はここからです(笑) 自分のアプリは当然ながら32bitで動かしてきたのでが、ここでプラットフォームをx64に変更し、古いってか、32bit版のJV-Linkへの参照を一旦削除して、もう一度COM 参照を追加するとしっかりかわるのですが、コードはそう簡単ではないですね。まずはJVGetのSafeArray関連で引っかかります。これまでは

// JVGetsとSafeArray関連
strFileName = new string('\0', iNameSize);
object objBuff = (object)(IntPtr)0;

と宣言してましたが、まあ、ここはそれ程重要ではないかもですが、

object objBuff = null;

とobjBuffの部分を変更、

// JVGets で1行読み込み
iReturnCode = SaraD.clsJVLink.JVGets(ref objBuff, iBuffSize, out strFileName);
if (iReturnCode > 0)
{
    bBuff = new byte[iReturnCode];
    IntPtr pSafeArray = (IntPtr)(int)objBuff;
    try
    {
        uint hr;

        IntPtr ppvData = (IntPtr)0;
        hr = SafeArrayAccessData(pSafeArray, ref ppvData);
        if (hr != 0) throw new System.Exception(hr.ToString());

        Marshal.Copy(ppvData, bBuff, 0, iReturnCode);

        SafeArrayUnaccessData(pSafeArray);
    }
    finally
    {
        SafeArrayDestroy(pSafeArray);
    }
}

JVGet後の取得多バッファはSafeArray使ってこんな感じにしてた部分は

IntPtr pSafeArray = IntPtr.Zero;

if (objBuff is IntPtr ptr)
{
    pSafeArray = ptr;
}
else if (objBuff is long l)
{
    pSafeArray = new IntPtr(l);
}
else if (objBuff is int i)
{
    pSafeArray = new IntPtr(i);
}
else if (objBuff != null)
{
    pSafeArray = new IntPtr(Convert.ToInt64(objBuff));
}

// ポインタが正しく取れているか念のためチェック
if (pSafeArray != IntPtr.Zero)
{
    uint hr;
    IntPtr ppvData = IntPtr.Zero;
    try
    {
        hr = SafeArrayAccessData(pSafeArray, ref ppvData);
        if (hr != 0) throw new System.Exception($"SafeArrayAccessData Error: {hr}");

        Marshal.Copy(ppvData, bBuff, 0, iReturnCode);

        SafeArrayUnaccessData(pSafeArray);
    }
    finally
    {
        SafeArrayDestroy(pSafeArray);
    }
}

としなければエラーが出てしまう。更に、このbBuffに格納される内容がどうもズレてくる感じまでは昨晩分かったけど、今日はその辺りのデバッグですorz

追記 2026.8.8 13:04
デバッグ進めると、まあ、今回はGeminiなんですが、騙されてました。上記のJVGets関連ですが、まず、objBuffの変更ですが、

object objBuff = new byte[0];

とするのが正解でした。更に、どうやら32bit版ではSafeArray使ってメモリの解放をする必要があったのですが、

VB以外の言語では、VARIANT*によってバイト型 SafeArray のポインタを受け取り、Return する際 にJV-Link内部で確保したByteSafeArrayをセットして返します。 途中の動作はすべてJVRead と共通しているので、JVGets → JVRead → JVGets というように交 互に呼ばれたとしても、矛盾なくレコードが取得できるように構成されています。 また、JVGets ではメモリの解放を行わないので、アプリケーション側で読み出しの度に解放する必 要があります。

どうやらその必要が無くなる様で、

if (objBuff is byte[] returnedBytes)
{
    if (returnedBytes.Length == iReturnCode)
    {
        bBuff = returnedBytes;
    }
    else
    {
        // 万が一、割り当てられたバッファ長と iReturnCode に差がある場合のみ切り出し
        bBuff = new byte[iReturnCode];
        Array.Copy(returnedBytes, bBuff, iReturnCode);
    }
}

としておけば、メモリリークの心配も無いとの事。

追記 2026.8.8 13:51
無事にフルセットアップがx64で終わりました。

微妙にメモリリークが出てる気がするしorz 遅くなったのは不明ですね。

0 件のコメント:

コメントを投稿