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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Visual Studio 2013

Microsoft Visual Studio 2013は、Microsoftによる統合開発環境(IDE)であり、多種多様なプログラミング言語に対応しています。 Visual Studio 2012の次のバージョンです

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

2回答

1277閲覧

PMX18-5AのサンプルプログラムVBをC++に書き直したい

ryop9982

総合スコア15

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Visual Studio 2013

Microsoft Visual Studio 2013は、Microsoftによる統合開発環境(IDE)であり、多種多様なプログラミング言語に対応しています。 Visual Studio 2012の次のバージョンです

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2018/08/10 08:36

編集2018/08/19 01:07

前提・実現したいこと

VBのプログラムをC++で書き直したい。
いろいろなサンプルプログラムを読みPMX18-5Aの電源装置をプログラムで通信しているということは確認できました。
しかし、電圧、電流を扱う部分の書き方がVBをC++に直す際にわかりません。

Private Sub cmdCurr_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdCurr.Click msg.WriteString("OUTP 0" & vbLf) msg.WriteString("VOLT 10" & vbLf) msg.WriteString("CURR 5" & vbLf) msg.WriteString("OUTP 1" & vbLf) End Sub

この部分をC++に書き直そうと思ったのですが、どうしたらいいのでしょうか・・・
1週間調べたのですがなかなか理解できず何か助言をいただけないでしょうか?

該当のソースコード

VB

1Imports Ivi.Visa.Interop 2 3 4 5Public Class Form1 6 7 8 9 Dim rm As ResourceManager 10 11 Dim msg As IMessage 12 13 14 15 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 16 17 rm = CreateObject("VISA.GlobalRM") 18 19 ' msg = rm.Open("MYDEV1", AccessMode.NO_LOCK, 0, "") 'VISAエイリアスを使用した例 20 21 'msg = rm.Open("USB0::0x0B3E::0x1029::00000001::INSTR", AccessMode.NO_LOCK, 0, "") 'USBを使用した例 22 23 msg = rm.Open("TCPIP::192.168.11.2::inst0::INSTR", AccessMode.NO_LOCK, 0, "") 'LANを使用した例 24 25 msg.TerminationCharacterEnabled = True 26 27 28 29 End Sub 30 31 32 33 'IDの問い合わせ 34 35 Private Sub cmdIdn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdIdn.Click 36 37 msg.WriteString("*IDN?" & vbLf) 38 39 TextBox1.Text = msg.ReadString(256) 40 41 End Sub 42 43 44 45 '電圧設定、電流設定 46 47 Private Sub cmdCurr_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdCurr.Click 48 49 msg.WriteString("OUTP 0" & vbLf) 50 51 msg.WriteString("VOLT 10" & vbLf) 52 53 msg.WriteString("CURR 5" & vbLf) 54 55 msg.WriteString("OUTP 1" & vbLf) 56 57 End Sub 58 59 60 61 '電圧測定値の問い合わせ 62 63 Private Sub cmdMeas_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdMeas.Click 64 65 msg.WriteString("MEAS:VOLT?" & vbLf) 66 67 TextBox1.Text = msg.ReadString(256) 68 69 End Sub 70 71 72 73 Private Sub Form1_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed 74 75 msg.Close() 76 77 End Sub 78 79End Class 80 81

C++

1#include"stdafx.h" 2#include"visa.h" 3 4int _tmain(int argc, _TCHAR* argv[]){ 5 ViSession rm, inst; 6 ViSession viError; 7 viError = viOpenDefaultRM(&rm); 8 viError = viOpen(rm, "TCPIP::192.168.11.2::inst0::INSTR", VI_NULL, VI_NULL, &inst); 9 10 viError = viPrintf(inst, "*IDN? \n"); 11 12 char buf[256]; 13 viError = viScanf(inst, "%256t", buf); 14 printf("*IDN?:%s\n", buf); 15 16 viError = viClose(inst); 17 viError = viClose(rm); 18 19 getchar(); 20 21 return 0; 22 23}

C++

1#import "C:\Program Files\IVI Foundation\VISA\VisaCom64\GlobMgr.DLL" no_namespace named_guids 2 3IMessagePtr spMsg; 4IMessage* pMsg = NULL; 5 6HRESULT hr; 7IResourceManager3Ptr spRM; 8hr = spRM.CreateInstance(CLSID_ResourceManager); 9 10IMessagePtr spMsg; 11spMsg = spRM->Open(L"TCPIP::192.168.11.2::inst0::INSTR", NO_LOCK, 0, L""); 12 13SAFEARRAY* pSA = NULL; 14try { 15 pSA = spRM->FindRsrc(L"?*INSTR"); 16 r = spmsg->WriteString(L"CURR 20.0\n"); 17 r = spmsg->WriteString(L"VOLT 5.5\n"); 18 19} 20catch (_com_error e) { 21 //エラー・コードとメッセージは_com_error クラスのメンバー関数から取得できる 22 HRESULT hr = e.Error(); 23 _bstr_t strDescription = e.Description(); 24} 25if (pSA) { 26 27 BSTR* rgElems = NULL; 28 ::SafeArrayAccessData(pSA, (PVOID*)&rgElems); 29 ASSERT(rgElems); 30 LONG lLBound, lUBound; 31 ::SafeArrayGetLBound(pSA, 1, &lLBound); 32 ::SafeArrayGetUBound(pSA, 1, &lUBound); 33 for (long lNdx = lLBound; lNdx <= lUBound; lNdx++) { 34 _bstr_t strFound = rgElems[lNdx]; 35 } 36 ::SafeArrayUnaccessData(pSA); 37 ::SafeArrayDestroyData(pSA); 38} 39 40 41spMsg->Close(); 42

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

Visual Studio2013
KI-VISA

自己解決方法

読み照らしながらC++で電圧値をプログラムから通信で変更することができました。
そのソースです。

#include "stdafx.h"
//タイプライブラリの作成

int _tmain(int argc, _TCHAR* argv[])
{
IMessagePtr spMsg; //スマート・ポインタ IMessagePtr型でCOMインターフェースを宣言、呼び出しを自動化している
CoInitializeEx(NULL, COINIT_MULTITHREADED); //COMを使うための宣言
HRESULT hr;
IResourceManager3Ptr spRM;
hr = spRM.CreateInstance(CLSID_ResourceManager); //CreateInstance()メソッドを使ってリソース・マネージャを作成

spMsg = spRM->Open(L"TCPIP::192.168.11.2::inst0::INSTR", NO_LOCK, 0, L""); //インターフェースの参照 SAFEARRAY* pSA = NULL; pSA = spRM->FindRsrc(L"TCPIP?* INSTR"); int r; r = spMsg->WriteString(L"OUTP 0 \n"); r = spMsg->WriteString(L"VOLT 10.0 \n"); r = spMsg->WriteString(L"CURR 5.0 \n"); r = spMsg->WriteString(L"OUTP 1 \n"); spMsg->Close(); //閉じる return 0;

}

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

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

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

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

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

guest

回答2

0

ベストアンサー

VB のコードをそのまま、C++に書き換えれば、良いのではないでしょうか?
(文法レベルの書き換え)
メーカーのサイトに資料があるみたいなので、それを元に、VBコードが何をしているか、調べ、 C++ に置き換えると手順が妥当ですが、元のVBコードは比較的、シンプルなので、そのままでも OKかと。(... と思ったが、ライブラリ提供しているメーカーがどの C++を想定しているか要確認)

msg.WriteString("OUTP 0" & vbLf)

--> msg.WriteString("OUTP 0\n"); // で良いかも

ただ、元のVBコードは、

msg = rm.Open("TCPIP::192.168.11.2::inst0::INSTR", AccessMode.NO_LOCK, 0, "") 'LANを使用した例
msg.TerminationCharacterEnabled = True

となっていますが、対応する C++ コードがありません。

また、VBが Formアプリに対し、C++ が tmain()で始まっていますが、何かあるのでしょうか? また、検索して引っ掛かったのが、 C# が多かったですが、 C++にこだわる理由はなにかありますか? (メーカーのサポート対象になってますか?)

投稿2018/08/10 09:22

pepperleaf

総合スコア6383

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

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

ryop9982

2018/08/10 10:08

メーカのライブラリはC++は対応しているみたいです。 ただ、C++/CLI、C#、VBが多くコードの書き換えがなかなか理解できません・・・ msg = rm.Open("TCPIP::192.168.11.2::inst0::INSTR", AccessMode.NO_LOCK, 0, "") 'LANを使用した例 msg.TerminationCharacterEnabled = True 此処に関してはメーカのC++の書き方に対応するようなものを探してみます・・・ C++にこだわる理由は、別の作った画像認識のプログラムがあるのですが その画像認識のプログラムで得た角度に応じて流す電圧値を変えていくというプログラムを最終的に作りたくて その画像認識のプログラムがC++で作ったためつなげやすいようC++で書こうかなと考えています。
pepperleaf

2018/08/10 10:53

画像処理プログラムは、C++/CLI に対応しているでしょうか? C++/CLIは、MS 独自仕様(?) で、普通のC++ と違うという事も聞きます。(詳しくないので、詳細は勘弁) こちらも確認された方が、後の苦労も少ないと思います。地道に調べれば、なんとかなる場合が多いですが、トラップも沢山待ってます。 > msg = rm.Open("TCPIP::192.168.11.2::i ..... このあたりは、さっき検索したら、C# ソースは見つかりました。(メーカードキュメント) C++ については、未確認。
yumetodo

2018/08/10 13:22

多分C#で書くほうが幸せだと思うなぁ、C++/CLIやるよりは
ryop9982

2018/08/11 07:26

そうですよね・・・ 少し別のアプローチを考えたいと思います・・・ お付き合いくださりありがとうございました
pepperleaf

2018/08/11 08:35

何が良いかは色々と見解はあるでしょうが、 一つの問題として、最近のVisualStudio では、C++は非推奨となっており、標準設定では、新規Formアプリが作れません。(メンテナンスは OK) 画像処理プログラムが画面表示まで行っていると大変かも知れませんが、内容次第では、C#移行の検討対象にしても良いのではないでしょうか? C++/CLI だったら、C#移行はそんなに大変では無いと思います。
ryop9982

2018/08/11 08:43

C++のプログラムに電圧値の操作を書き足そうと思ったのですが 質問なのですが、 msg.WriteString("OUTP 0\n"); と書いた場合クラスを作らないといけないと思うのですが この場合どのように作っていくのでしょうか・・・ class t::_tmain(int argc, _TCHAR* argv[]){ public: int msg; }; 自分はこのようにして書いたのですがエラーがでました・・・ この辺りはどうしたらよいのでしょうか・・・
ryop9982

2018/08/11 08:46

そうだったのですね・・・ 本当は画像認識のプログラムに電圧値だけ書き足してメインは画像認識と思っていたのですが 電源装置のプログラムに関して全然わからず困っていました。 お盆終わりに周りの人と相談をして考えてみます・・・ 図書館などしまってますし調べるのも苦労なので・・・????
pepperleaf

2018/08/11 09:06 編集

> msg.WriteString("OUTP 0\n"); > と書いた場合クラスを作らないといけないと思うのですが 上のコメントにもちょっと書きましたが、VBコードを見ると IMessage クラスです。これは、状況的に、メーカー提供のライブラリクラスです。 で、作るのはクラスで無く、オブジェクト。(この辺は記法の相違のみで VBも同じ) これに対応するのが、C++ では何かという事です。多分、同じ名前であると思いますが、推測なので、確認する必要があるという事です。 あっ、と、この辺の情報は図書館で難しいです。メーカーサイトにドキュメントがある筈なので、探しましょう。
ryop9982

2018/08/12 16:44

https://www.kikusui.co.jp/download/doc/KiVisaGuide_2012(July)_J.pdf のP103にC++の記述方法がかかれていました。 IMessageのクラスと教えていただいて少し概要がわかった気がします! インターフェースの参照で spMsg=spRM->Open(L”TCPIP::192.168.11.2::inst0::INSTR”,NO_ROCK,0,L”); で r=songs->WriteString(L”VOLT 5.5 /n”); などでできるんじゃないかなと思いました。 PMX18-5Aがいまリコールで持っていかれてしまったので現在試せないですが、試したいと思います。 ありがとうございます!
yumetodo

2018/08/13 07:20

というかよく見たらただのTCP/IPか・・・?ソケット通信ならboost:asio使うという手もある。
ryop9982

2018/08/13 10:43

boost:asioは初めて知りました… TCPで同期通信だったり、非同期I/Oライブラリと書いてありました たしかに使えそうな気がします。 調べて少しやってみようと思います ありがとうございます!
pepperleaf

2018/08/13 12:53

> ソケット通信ならboost:asio使う それを使うのも良いかもしれませんが、その場合、メーカー提供ライブラリは使えないと理解しましょう。(アクセスが競合するため) どちらが良いかは、担当者の責任ですが、まあ、一般的には、メーカーライブラリでしょう。(こちらの場合、メーカーに問合せできる)
yumetodo

2018/08/13 14:47

補足ありがとうございます。
pepperleaf

2018/08/15 11:25

質問を更新されたようですが、更新内容に関する説明が無く、2つの C++ソースの関係が不明です。 また、tmain()がある方の記述は、何を行っているのでしょうか? KiVisaGuide_2012(July)_J.pdf の P.34 辺りからも、アクセス手順に関する記述もありますね。 VBソースと合わせて対応を確認されたでしようか? また、WriteString() の文字列に L"" (ワイド文字指定)とされていますが、これは大丈夫でしょうか? 電源装置に送る文字列は、Ascii文字だと思うのですが、ちょっと自信無し。
ryop9982

2018/08/15 14:48

パソコンを実家に置いて途中切り上げて更新を途中にしてしまいました…… スマートフォンで書き足します、すみませんでした汗 一つ目は消す予定でした汗 二つ目はこれでPMXと通信できるのではないかとまだ途中のプログラムを載せてしまいました… すみません、すべてが中途半端になっています 本当はこのC++をtmainに入れてやる予定でした。 一応、C++環境では、COMインターフェースをアクセスする際に扱われる文字列はすべてUNICODEになる。 リテラル(直値文字列)を記述する場合にはLが付く と文字列の扱いの部分に記載されていたのでこのようにしようとしていました。 詳しくは、また明日更新します。 変に更新してしまい申し訳ありませんでした……
yumetodo

2018/08/15 15:10

そういうときは質問を分けましょう。質問内容を消すとか後で遡及できないことはやめましょう
ryop9982

2018/08/15 15:38

コメントありがとうございます。 たしかにそうですね。 下に分けて書きます。
yumetodo

2018/08/16 09:43

じゃなくて別途質問を投げては?という話だったんですが。質問したいことがそろそろなんなのかわからなくなってきているし。
pepperleaf

2018/08/16 10:20 編集

質問内容は変わっていないと思いますよ。 C++ で、PMX18-5A の制御(通信)を行いたいと言う事と理解しています。 ただ、元の質問主旨が本質で無かったのと、方向性の違う回答に振り回されている感じはありますが、、、。 また、質問者さんが、C++ の基本的なところを理解していない感じもするので、合わせて理解するのは大変かとも思います。
ryop9982

2018/08/19 01:14

返信遅れてしまい申し訳ございませんでした。 boost.aisioも試そうと思ったのですがプログラムのソースファイルが開かないというエラーをいじっていたり、変に中途半端なコードを書き直したりしていたため長い間返信が遅くなってしまいました。 C++の書き方でVBのコードに電圧の部分を書き換えてみたところ電圧値の変更に成功することができました。 まだいろいろ試していこうと思うのですがとりあえずyumetodoさんがおっしゃったように質問が分からなくなっているとのことと、一番C++でほしかったコードの結果を得ることができたので質問を pepperleafさんの回答でベストアンサーにしたいと思います。 長い期間pepperleafさんお付き合いいただきありがとうございました。
pepperleaf

2018/08/19 08:23

コメントに漏れていたかと思いますが、KI Visa ライブラリは、TCP/IPだけでなく、USBとか、他の I/F にも対応しているみたいですね。 Open時のオプションを変更するだけで。 boost.aisio の方が、ソフトウエア的には面白いかも知れませんが、計測機器の制御という観点から、ちょっと疑問。 参考までに。
guest

0

msg.WriteString("OUTP 0" & vbLf)

ふつーに、
int x=0;
sprintf(msg,"OUTP %d\n",x);
でいけるんじゃないでしょうか

投稿2018/08/10 08:47

y_waiwai

総合スコア87747

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

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

ryop9982

2018/08/10 09:43

sprintfを使用すると error C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. のエラーでspirintf_sを使用しようとしたのですが error C2664: 'int sprintf_s(char *,size_t,const char *,...)' : 引数 2 を 'const char [9]' から 'size_t' へ変換できません。 IntelliSense: オーバーロードされた関数 "sprintf_s" のインスタンスが引数リストと一致しません 引数の型: (ViString, const char [9], int) とのエラーで使用することができませんでした。 このエラーは何故でしょうか・・・?
episteme

2018/08/10 09:53

↑使い方間違ってるから。 char buf[100]; sprint_s(buf, 100,"フォーマット"...) みたく、文字列を詰め込むエリアの"大きさ"を引数に与えんと。
ryop9982

2018/08/10 10:16 編集

すみません。 勉強します。 使い方を間違えていました・・・ ちゃんと調べて一つ一つ書きたいと思います・・・ ありがとうございました。
pepperleaf

2018/08/10 10:45

> msg.WriteString ここの msg はメーカー提供クラスのオブジェクト。従って、sprintf() に置き換える事自体が無意味。 (まあ、文字列にして そのまま、出力はありだけど)
y_waiwai

2018/08/10 11:13

ああ、VisualStudioではscanfとかprintfは使えないようになってる。 とにかく、ふつーにASCII文字列を送信するようにすればコントロールできるから、そうするべし。
ryop9982

2018/08/11 08:22

答えてくださりありがとうございます。 ASCII文字列で操作方法がわからないので調べてやっていますがASCII文字列で電圧値の操作がよくわからず調べても出てこないので 時間がかかりますがまた時間が経って質問してもいいでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問