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