質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
DLL

DLL(Dynamic Link Library)とは、他のモジュールからも使用する事が出来る、関数とデータが格納されているモジュールのことです。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

Q&A

解決済

1回答

979閲覧

WindowsフォームアプリケーションにてDllを使いたい

changryu

総合スコア3

DLL

DLL(Dynamic Link Library)とは、他のモジュールからも使用する事が出来る、関数とデータが格納されているモジュールのことです。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

1グッド

0クリップ

投稿2023/06/20 04:58

はじめに

知識が浅いため、間違った言葉、表現、そもそも認識間違いがあるかも知れません。
その際はご指摘頂けますと勉強になりますので有り難いです。どうぞ宜しくお願い致します。

実現したいこと

WindowsフォームアプリケーションにてDllの使い方を知りたいです。

前提

現在、WindowsにてI/O信号を制御するアプリケーションを作成しています。

I/O信号はTCTEC社のTOP16というUSB I/Oボードを使用します。
販売元のエレファインにて、C#用サンプルコードと使用するDllファイルが提供されており、動作確認をしたところコンソールアプリだったので、これをベースにフォームアプリを作っています。
現在の目標は、同様に提供されているTop16 Manager2.3と同じ機能を実現したいと考えています。

イメージ説明
このTop16 Manager2.3の動きを簡単にですがご説明しますと、アプリ起動時にTop16ボードが繋がっていれば上記のようにBorad名の表示とin 1-8の状態検出します。
インプット信号はプルアップしているのでインプットがOFF時にハイレベルとなり色が紫色に変わっています。
起動後に例えばインプット in 1を外部スイッチからONにするとリアルタイムにセルの色が白くなります。
ただし仕様なのか起動後にin 1 - in 8のセルをクリックしなければそれぞれのGainの値は表示はされませんが、一度表示するとその後はリアルタイムに値を表示します。

まずはこのTop16 Manager2.3のようにインプットがON時の状態をリアルタイムに検知できるようにと考えています。

発生している問題・エラーメッセージ

提供されているDllをどうやって使ってリアルタイムにインプット信号が検出できるか分からず、まだエラーメッセージを発生させるに至っておりません。

該当のソースコード

まずはインプット信号(in 1)のみをリアルタイムで検出できるよう検討しています。
イメージ説明

C#(Form1.cs)

1using System; 2using System.Collections; 3using System.Text; 4using System.Windows.Forms; 5using System.IO; 6using System.Drawing; 7 8namespace Top16_TestWinForm 9{ 10 public partial class Form1 : Form 11 { 12 public Form1() 13 { 14 InitializeComponent(); 15 StartPosition = FormStartPosition.CenterScreen; 16 } 17 18 private void Top16Refresh() 19 { 20 try 21 { 22 //ここからTOP16の制御 23 const int MAX_NO_BOARDS = 124; 24 const int MAX_NAME_LEN = 20; 25 26 //使用しているDllバージョンの表示 27 string outstring1 = "DLL version = " + Top16.dllversion() + "\n"; 28 label4.Text = outstring1; 29 30 // Read the number of boards and names 31 byte[] byBoardNames = new byte[MAX_NO_BOARDS * MAX_NAME_LEN]; 32 Int32 boardsFound = Top16.ListTop16Boards(byBoardNames); 33 String sListOfBoards = Encoding.ASCII.GetString(byBoardNames, 0, MAX_NO_BOARDS * MAX_NAME_LEN); 34 35 //TOP16ボードの枚数表示 36 string outstring2 = Convert.ToString(boardsFound); 37 label6.Text = outstring2; 38 39 // Make a list of all the board names 40 ArrayList sBoardNames = new ArrayList(); 41 for (int i = 0; i < boardsFound; i++) 42 { 43 // List the names of all Top16 boards found, and add them to an ArrayList 44 //TOP16の名前表示 45 sBoardNames.Add(sListOfBoards.Substring(i * MAX_NAME_LEN, MAX_NAME_LEN)); 46 String outstring3 = sBoardNames[i] + "\n"; 47 dataGridView1.Rows[0].Cells[0].Value = outstring3; 48 } 49 50 //画面ロード時に一度インプット状態を検知する 51 for (int i = 0; i < sBoardNames.Count; i++) 52 { 53 UInt64 handle = Top16.OpenBoard(new StringBuilder((String)sBoardNames[i])); 54 if (handle > 0) 55 { 56 // read an analog input まずはインプット1のみ 57 int aInput = Top16.readAnalogInput(handle, 1, (byte)'Z'); 58 59             //いくつかサンプリングし3998以上で未入力状態 60 if (aInput > 3998) 61 { 62 dataGridView1.Rows[0].Cells[1].Style.BackColor = Color.Blue; 63 } 64         65             //Gainの表示 66 String outstring5 = Convert.ToString(aInput); 67 label8.Text = outstring5; 68 69 // close the board 70 // 71 Top16.CloseBoard(handle); 72 } 73 } 74 } 75 catch (Exception ex) 76 { 77 // Display an error if caught 78 79 MessageBox.Show(ex.Message); 80 } 81 } 82 83 private void Form1_Load(object sender, EventArgs e) 84 { 85 //ロード時にインプット信号の状態をとる 86 Top16Refresh(); 87 } 88 89 private void button1_Click(object sender, EventArgs e) 90 { 91 //ボタン操作でインプット状態の更新する 92 Top16Refresh(); 93 } 94 } 95} 96

C#(Top16.cs)

1using System; 2using System.Runtime.InteropServices; 3using System.Text; 4 5namespace Top16_TestWinForm 6{ 7 public class Top16 8 { 9 [DllImport("top16_64.dll")] 10 public static extern Int32 dllversion(); 11 12 [DllImport("top16_64.dll")] 13 public static extern Int32 ListTop16Boards(byte[] sBoardNames); 14 15 [DllImport("top16_64.dll")] 16 public static extern Int32 SetOutputs(UInt64 Handle, Byte mask, Byte set); 17 18 [DllImport("top16_64.dll")] 19 public static extern Int32 GetInputs(UInt64 Handle); 20 21 [DllImport("top16_64.dll")] 22 public static extern Int32 readAnalogInput(UInt64 Handle, Int16 input, byte gain); 23 24 [DllImport("top16_64.dll")] 25 public static extern UInt64 OpenBoard(StringBuilder boardName); 26 27 [DllImport("top16_64.dll")] 28 public static extern Int32 CloseBoard(UInt64 Handle); 29 } 30}

試したこと

まずは安易に検出部のメソッドTop16Refresh();をWhile文で回していれば検出できるかと考えました。

駄目だったこと
・ループ中は他の操作ができない(ビジー状態?)
・インプットを検出できない
・試してはいませんが、もし仮にループから抜けさせても、再びボタン操作をしないと次のインプットを検出できないのでは。それでは目的と異なる。

それでそもそもDllの使い方を間違っているのではないかと思い、ここ三日間ほどインターネットを検索をしているのですが専門用語が分かっていないのか?期待する説明が見つけられずteratailにたどり着きました。

補足情報(FW/ツールのバージョンなど)

Microsoft Visual Studio Community 2022
Version 17.5.5
VisualStudio.17.Release/17.5.5+33627.172
Microsoft .NET Framework
Version 4.8.09032

think.fukuを押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YAmaGNZ

2023/06/20 05:19

ループではなく1回だったら値は取れているのですか?
changryu

2023/06/20 05:29

GAINの値はウインドウ起動(ロード)時、ボタンクリック時はON状態、OFF状態で取れています。ご質問頂いてからdataGridViewの色は切り替わらないことに気づき、ON時の判断を追加したいと思います。
YAmaGNZ

2023/06/20 05:44

1回でも値が取れているのであればDLLの使い方ということではなくWindowsフォームのプログラムの作り方の方法を理解しきれていないのではないかと思われます。 やりたいことがどのようなことなのか細かいことは分かりませんが、タイマーを利用してそのタイマーで1回読み込むというものを作ってみてはどうでしょうか。
changryu

2023/06/20 05:56

ありがとうございます。 そもそもプログラミングもC#も未熟なため、目的とするプログラムの作り方が分からなかったので、もしかしたらDllの使い方が間違っているのでは?と思うようになっていました。 早速、タイマー調べてみます。助言に感謝致します。
changryu

2023/06/20 08:22

YAmaGNZ様 タイマー使ってみました。結論として想定していた動きができました。 解決方法をまた別途記載しますが、取り急ぎお礼をさせて頂きます。 この度は迷える初心者をお導き頂き、ありがとうございました。
changryu

2023/06/20 08:40

kikukiku様 この度は、参考URLを教えて頂きまして誠にありがとうございました。 タイマーはこれまで使用したことがなかったで、これを機にいつでも使えるようように勉強してみます。
changryu

2023/06/20 08:53

YAmaGNZ様 もし宜しければベストアンサーを差し上げたいので回答に頂ければ有り難い限りです。 ご検討のほど宜しくお願い致します。
guest

回答1

0

自己解決

Dllの使い方ではなく、プログラムの作り方でした。
今回のDllの出番はDllImportで関数を利用するだけでした。

解決方法

タイマーを使いリアルタイムでONOFF状態を検出できました。

その他

タイマーを使った当初のソースコードではreadAnalogInput関数のGain値でインプットのONOFFを判断していました。
ただ、Gain値でもONOFFの判断はできるのですが、問題がありました。

問題1. Gain値が安定しない。サンプリングが必要。場合よっては将来的に変わる可能性?
問題2. Top16ボードにあるアクセスランプがタイマーで実行されるたびに点滅する。

特に気になったのは問題2のアクセスランプの点滅で、今回見本としているTop16 Manager2.3ではONOFFの検出だけであればアクセスランプはほとんど点滅しませんでした。

それでもしかしたらタイマーを使った検出とは違うのかも?と思いましたが、改めてじっくりとソースコードを見ていたところ、今回使用するDllにGetInputs関数(関数?)というものが有ることに気づきました。

それでこちらを使ってインプットのONOFFを検出してみたところ、アクセスランプの点滅はしないことが分かりました。

最後に

Top16 Manager2.3ではロード時からGain値は取得できないので不思議に思っていたのですが(最初からGain値も取れる)、ここからは私の想像になりますが、もしかしたら何かしら理由があって(ボードの保護?)Gain値を必要としない監視ならGetInputs関数を使用するものだと思いました。

投稿2023/06/20 08:43

changryu

総合スコア3

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YAmaGNZ

2023/06/20 10:41

ベストアンサーに関しては自己解決としておいてもらって結構です。 ただ、ボードのOpen/Closeに関しては頻繁に行わなくてもいいような気はします。 フォームロード時にOpenして終了時にCloseし、タイマー処理ではInputの取得のみ行うという形です。 実際のボードやDLLがどのように動作するのかは分かりませんが、アナログのふらつきにも関係するかもしれません。 Top16 Manager2.3というソフトにてリアルタイムでアナログ値のモニタが出来るのかは分かりませんが、そちらで値がふらつかないのであればそういった部分も関係ある可能性は考えられるかと思います。
changryu

2023/06/21 05:37

ご返信遅くなり申し訳ございませんでした。 先に、ボードのOpen/Closeのアドバイスですが、思わず手をポンと叩いてしまいました。 まだ実際に試してはいませんが、なんとなく胸にスッと落ちる感覚がありました。 是非とも試してみたいと思います。 それとベストアンサーに関して、ご配慮に感謝致します。 私もいずれはYAmaGNZ様のように経験値を積み、迷える初心者にアドバイスできるよう精進したいと思います。 改めてお礼申し上げます。この度はありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問