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

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

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

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

C++

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

Q&A

解決済

1回答

819閲覧

国税の電子申告用DLL利用方法

momoxxx

総合スコア1

C#

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

C++

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

0グッド

0クリップ

投稿2023/03/19 14:05

実現したいこと

C++のDLLをC#で利用したいです。

C#から対象のDLLが利用可能なのかどうか?を初めに伺いたく、
もし利用可能なのであれば、利用方法をご教示頂けますと幸いです。
もし利用不可でC++でラッパークラスを作成する必要がある、といった場合は
C++での利用方法をご教示頂けますと幸いです。

前提

国税庁が以下URLに出している国税の電子申告用DLL(C++で作られている)をC#から利用し、
ユーザーが電子申告までできるアプリケーションを開発しようとしています。
https://www.e-tax.nta.go.jp/shiyo/shiyo3.htm

私自身C++の知識が乏しいため、DLLの仕様書を読んでもC#から呼び出す方法がわからず困っております。
以下のようなサイトを参考にして、関数の呼び方はわかったのですが、
DLL側が関数を呼び出せる形になっていないようにも思っています。
https://www.fenet.jp/dotnet/column/language/9830/

利用できない場合はC++でC++のDLLを利用するラッパークラスを作成し、C#から呼び出せる形にする
という記事もありました。

発生している問題

仕様書の内容を一部以下に抜粋します。

該当の送受信モジュール仕様書

送受信モジュールの使用手順について以下に示す。
(1) 通信前の準備手順
① CLCommunication インターフェイスを作成する。
② 画面 ID を変換する場合には、SetConversionClassName 関数を発行し、画面 ID 変換クラ スを生成する。
③ 受付システムへの Login 認証とメインメニューからのリンク先は、プロパティファイルを 使用して設定する必要があるため、AttestationUrl 関数を発行し、サーバのアドレスとリン ク先をそれぞれ読み込ませる。

上記の①の時点で理解ができておりません。
恐らくインスタンスを生成することなのだと理解しましたが、
C#からC++のDLLを呼び出してインスタンス生成する方法が調べてもわからっていないです。

補足情報

電子申告用DLL(C++で作られている)をC++で利用するサンプルコードは国税庁が提供してくれています。

C++

1// TestCommVC01.cpp : コンソール アプリケーション用のエントリ ポイントの定義 2// 3 4#include "stdafx.h" 5#include "iostream" 6 7// 送受信モジュール 8#import ".\bin\CLCommunication.dll" 9 10// 使用する名前空間 11using namespace std; 12using namespace CLCOMMUNICATIONLib; // 送受信モジュール 13 14// エラー表示用 15#define CREATE_REQUEST "CreateRequest" 16#define SEND "Send" 17#define GET_HTTPSTATUS_CODE "GetHttpStatusCode" 18#define GET_RESPONSE "GetResponse" 19#define GET_ERRORRESPONSE "GetErrorResponse" 20#define SET_PARAMETER "SetParameter" 21 22#define USER_ID "1111111111111" 23#define PASSWORD "Pass0001" 24 25//========================================================= 26// TestCommVC01 27// 28// 概要:e-taxソフトの送受信モジュールの簡単なサンプル 29// 説明:このモジュールでは、利用者識別番号と暗証番号を 30// 指定して認証処理を行い、次いでメッセージボックス 31// から最初のメッセージを取り出し、タイトルを表示 32// する例です。 33//========================================================= 34int main(int argc, char* argv[]) 35{ 36 // 変数宣言 37 CLICommunicationPtr pComm = NULL; 38 CLIHttpRequestPtr pReq = NULL; 39 CLIHttpResponsePtr pRes = NULL; 40 41 _bstr_t bstrMessage; 42 char szMethod[64]; 43 44 int ret = 0; 45 HRESULT hr = S_OK; 46 47 VARIANT vtIndex; 48 VARIANT vtRes; 49 long nStatus = -1L; 50 51 _bstr_t bstrIniFile; 52 char szPath[_MAX_PATH+1]; 53 char szDrive[_MAX_DRIVE+1]; 54 char szDir[_MAX_DIR+1]; 55 56 57 //------------------------------------------------------------ 58 // プログラムの開始 59 // 60 61 // 変数の初期化 62 VariantInit(&vtIndex); 63 VariantInit(&vtRes); 64 65 // INIファイルはEXEの一つ上 66 ZeroMemory(szPath, _MAX_PATH+1); 67 ZeroMemory(szDrive, _MAX_DRIVE+1); 68 ZeroMemory(szDir, _MAX_DIR+1); 69 GetModuleFileName(NULL, szPath, _MAX_PATH); 70 _splitpath(szPath, szDrive, szDir, NULL, NULL); 71 bstrIniFile = szDrive; 72 bstrIniFile += szDir; 73 bstrIniFile += "\\..\\"; 74 bstrIniFile += "CLCommunication.ini"; // フルパス 75 76 // COM+の準備 77 hr = CoInitialize(NULL); 78 if(FAILED(hr)){ 79 cerr << "COM+の準備でエラー: " << hr << endl; 80 ret = 1; 81 goto TERMINATE; 82 } 83 84 // CLCommunicationインターフェイスの作成 85 hr = pComm.CreateInstance(__uuidof(CLCCommunication)); 86 if(FAILED(hr)){ 87 cerr << "CLCommunicationインターフェイスの作成でエラー: " << hr << endl; 88 ret = 2; 89 goto TERMINATE; 90 } 91 92 // 受付システムへのLogin認証とメインメニューからのリンク先を設定 93 hr = pComm->put_AttestationUrl(bstrIniFile); 94 if(FAILED(hr)){ 95 cerr << "受付システムへのLogin認証とメインメニューからのリンク先の設定でエラー: " << 96 hr << endl; 97 ret = 3; 98 goto TERMINATE; 99 } 100 101 //------------------------------------------- 102 // メインメニューを要求(認証) 103 //------------------------------------------- 104 try{ 105 ZeroMemory(szMethod, sizeof(szMethod)); 106 CopyMemory(szMethod, CREATE_REQUEST, sizeof(CREATE_REQUEST)); 107 pReq = pComm->CreateRequest("XU00S010"); // 認証(メインメニューの要求) 108 109 ZeroMemory(szMethod, sizeof(szMethod)); 110 CopyMemory(szMethod, SET_PARAMETER, sizeof(SET_PARAMETER)); 111 112 //======================================== 113 // 必要に応じてここのパラメータは変更する 114 // (ここでは適当な値を使用。 115 // 試す場合は適正な値に変えてください) 116 pReq->SetParameter("sUserId", USER_ID); // 利用者識別番号 117 118 try{ 119 vtRes = pComm->Send(); // 送信 120 } 121 catch(_com_error e){ } 122 123 ZeroMemory(szMethod, sizeof(szMethod)); 124 CopyMemory(szMethod, CREATE_REQUEST, sizeof(CREATE_REQUEST)); 125 pReq = pComm->CreateRequest("XU00S010_1"); // 認証実行 126 127 ZeroMemory(szMethod, sizeof(szMethod)); 128 CopyMemory(szMethod, SET_PARAMETER, sizeof(SET_PARAMETER)); 129 130 //======================================== 131 // 必要に応じてここのパラメータは変更する 132 // (ここでは適当な値を使用。 133 // 試す場合は適正な値に変えてください) 134 pReq->SetParameter("sUserId", USER_ID); // 利用者識別番号 135 pReq->SetParameter("sPwd", PASSWORD); // 暗証番号 136 137 try{ 138 vtRes = pComm->Send(); // 送信 139 } 140 catch(_com_error e){ } 141 142 ZeroMemory(szMethod, sizeof(szMethod)); 143 CopyMemory(szMethod, GET_HTTPSTATUS_CODE, sizeof(GET_HTTPSTATUS_CODE)); 144 nStatus = pComm->GetHttpStatusCode(); 145 if(nStatus != 200){ // 認証失敗 146 cerr << "認証エラー at Send; HTTP Status = " << nStatus << endl; 147 ZeroMemory(szMethod, sizeof(szMethod)); 148 CopyMemory(szMethod, GET_ERRORRESPONSE, sizeof(GET_ERRORRESPONSE)); 149 pRes = pComm->GetErrorResponse(); 150 if(pRes){ 151 bstrMessage = pRes->XML; 152 cerr << (char*)bstrMessage << endl; 153 } 154 else{ 155 cerr << "受付システムから正しいデータが取得できませんでした" << endl; 156 } 157 ret = 5; 158 goto TERMINATE; 159 } 160 } 161 catch(_com_error e){ 162 cerr << "認証エラー at " << szMethod << ": " << e.Error() << endl; 163 ret = 4; 164 goto TERMINATE; 165 } 166 cout << "認証成功" << endl; 167 168 //------------------------------------------- 169 // メインメニュー → メッセージボックス 170 //------------------------------------------- 171 try{ 172 ZeroMemory(szMethod, sizeof(szMethod)); 173 CopyMemory(szMethod, CREATE_REQUEST, sizeof(CREATE_REQUEST)); 174 pReq = pComm->CreateRequest("XU00S020_BUSINESS_2"); // メッセージボックス 175 176 ZeroMemory(szMethod, sizeof(szMethod)); 177 CopyMemory(szMethod, SEND, sizeof(SEND)); 178 try{ 179 vtRes = pComm->Send(); 180 } 181 catch(_com_error e){ } 182 183 ZeroMemory(szMethod, sizeof(szMethod)); 184 CopyMemory(szMethod, GET_HTTPSTATUS_CODE, sizeof(GET_HTTPSTATUS_CODE)); 185 nStatus = pComm->GetHttpStatusCode(); 186 if(nStatus != 200){ // メッセージボックス取得失敗 187 cerr << "メッセージボックス取得エラー at Send; HTTP Status = " << nStatus << endl; 188 ZeroMemory(szMethod, sizeof(szMethod)); 189 CopyMemory(szMethod, GET_ERRORRESPONSE, sizeof(GET_ERRORRESPONSE)); 190 pRes = pComm->GetErrorResponse(); 191 if(pRes){ 192 bstrMessage = pRes->XML; 193 cerr << (char*)bstrMessage << endl; 194 } 195 else{ 196 cerr << "受付システムから正しいデータが取得できませんでした" << endl; 197 } 198 ret = 5; 199 goto TERMINATE; 200 } 201 } 202 catch(_com_error e){ 203 cerr << "メッセージボックス取得エラー at " << szMethod << ": " << e.Error() << endl; 204 ret = 4; 205 goto TERMINATE; 206 } 207 cout << "メッセージボックス取得成功" << endl; 208 209 //------------------------------------------- 210 // メッセージ詳細 211 //------------------------------------------- 212 try{ 213 // レスポンスを取得 214 ZeroMemory(szMethod, sizeof(szMethod)); 215 CopyMemory(szMethod, GET_RESPONSE, sizeof(GET_RESPONSE)); 216 pRes = pComm->GetResponse(); 217 218 // 要求を作成 219 ZeroMemory(szMethod, sizeof(szMethod)); 220 CopyMemory(szMethod, CREATE_REQUEST, sizeof(CREATE_REQUEST)); 221 pReq = pComm->CreateRequest("XU00S090"); // (メッセージ)詳細表示 222 223 //======================================== 224 // 必要に応じてここのパラメータは変更する 225 // (今回は1番目のメールの詳細を取得) 226 vtIndex.vt = VT_I4; 227 vtIndex.lVal = 1L; // とりあえず1番目のメール 228 pReq->SetParameter("objSel", pRes->GetValue("内容_メール通番", vtIndex)); 229 230 ZeroMemory(szMethod, sizeof(szMethod)); 231 CopyMemory(szMethod, SEND, sizeof(SEND)); 232 try{ 233 vtRes = pComm->Send(); 234 } 235 catch(_com_error e){ } 236 237 // 結果のタイトルのみをとりあえず表示 238 ZeroMemory(szMethod, sizeof(szMethod)); 239 CopyMemory(szMethod, GET_HTTPSTATUS_CODE, sizeof(GET_HTTPSTATUS_CODE)); 240 nStatus = pComm->GetHttpStatusCode(); 241 if(nStatus == 200){ 242 ZeroMemory(szMethod, sizeof(szMethod)); 243 CopyMemory(szMethod, GET_RESPONSE, sizeof(GET_RESPONSE)); 244 pRes = pComm->GetResponse(); 245 bstrMessage = pRes->GetValue("タイトル"); 246 } 247 else{ 248 ZeroMemory(szMethod, sizeof(szMethod)); 249 CopyMemory(szMethod, GET_ERRORRESPONSE, sizeof(GET_ERRORRESPONSE)); 250 pRes = pComm->GetErrorResponse(); 251 if(pRes){ 252 bstrMessage = pRes->XML; 253 } 254 else{ 255 bstrMessage = "受付システムから正しいデータが取得できませんでした"; 256 } 257 } 258 cout << (char*)bstrMessage << endl << endl; 259 BSTR bsXml; 260 pRes->get_XML(&bsXml); 261 _bstr_t bsXmlVal = bsXml; 262 cout << (char*)bsXmlVal << endl << endl; 263 } 264 catch(_com_error e){ 265 cerr << "メッセージ詳細表示 at " << szMethod << ": " << e.Error() << endl; 266 ret = 4; 267 goto TERMINATE; 268 } 269 270// 共通終了処理(各種オブジェクトの解放等) 271TERMINATE: 272 pComm = NULL; 273 pReq = NULL; 274 pRes = NULL; 275 CoUninitialize(); 276 return 0; 277} 278

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

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

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

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

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

guest

回答1

0

ベストアンサー

提示されたリンクをざっと見た限りでは提供されている DLL はいわゆる COM の規約に従ったオブジェクトです。 様々なコンポーネントを利用しやすくする仕組みであり、 Windows 上で動く言語処理系の内でマイクロソフトが提供するもののおおよそは COM に対してのサポートがあります。 ラッパーを書く必要はなく C# から利用できると思います。 利用するだけなら C++ の知識は不要です。

COM の考え方は「サービスを提供するオブジェクト」がまず存在しており、そのオブジェクトが持つインターフェイスを通じてメソッドを呼ぶという形をとります。 仕様書で言うインターフェイスは COM 用語のインターフェイスのことだと思われます。

私は C# の文法や使い方に明るいわけではないので C# における具体的な手順を示すことが出来ないのですが COM について調べることをお勧めします。

投稿2023/03/19 14:38

SaitoAtsushi

総合スコア5444

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

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

momoxxx

2023/03/19 15:06

ご回答並びにリンクを見て頂いたり、ありがとうございます。 インターフェイスはCOM用語なのですね。 ありがとうございます!! 一度C#からCOMの利用方法についてインプットしてみます! 何をすれば良いかもわからない状態でしたので大変助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問