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

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

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

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

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

C++

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

Q&A

解決済

2回答

4419閲覧

C++でエクセルとのリンクを行うdllを作成する際の問題

cesolution

総合スコア217

DLL

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

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

C++

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

0グッド

0クリップ

投稿2016/08/26 05:04

###前提・実現したいこと
Visual Studio Express 2008でExcel用のdllファイルを作成しています。
プログラミングはほぼ初心者ですので、非常識な質問になっておりましたらすみません。
エクセル側から、x[2]、y[2]という2つの行列の値をdll内の関数に渡し、c++側のEigenライブラリで行列計算を行いたいと考えています。

###発生している問題・エラーメッセージ
c++のコード側で、Excelから読み込む配列が1つのみの時は、問題なく、全ての配列を読み込み、c++のdll側の変数に以下のように値を格納できます。
Matrix Aにx[0]、x[1]の値、Matrix Bにx[2]、x[3]の値。

しかし、配列の数を2つにすると、
Matrix Aにx[0]、x[1]、Matrix Bにy[0]、y[1]の値を格納したいのですが、確認したところ、どうも
Matrix Aにx[0]、0、Matrix Bにy[0]、0が入ってしまうようです。

試しにVBA側のコードを

vba

1 Debug.Print (Mult(x(0),y(1)))

とした所、
Matrix Aにx[0]、0、Matrix Bにy[1]、0が入ったようです。
どうも現状の設定の仕方だと、VBAで指定した先頭の値から、次の配列の値まで動いていないようです。
VBA側で指定した配列を複数dll側に渡すにはどのように設定すれば良いのでしょうか?
ご教授いただければ助かります。

エラーメッセージ:dllが正しくよみこめません

というエラーが発生します。

###該当のソースコード
元々のコード

c++

1double __stdcall Mult(double x[], double y[]) 2{ 3 4 MatrixXd z(1,1); 5 double z2[1]; 6 double z3; 7 8 MatrixXd A=MatrixXd::Ones(1,2); 9 MatrixXd B=MatrixXd::Ones(2,1); 10 11 A(0,0)=x[0]; 12 A(0,1)=x[1]; 13 B(0,0)=y[0]; 14 B(1,0)=y[1]; 15 16 z=A*B; 17 Map<MatrixXd>(&z2[0],1,1)=z; 18 z3=z2[0]; 19 20 return z3;

vba

1Private Declare Function Mult Lib "ExcelLink.dll" (x As Double, y As Double) As Double 2 3 '[1,2]行列 4 x(0) = 3 5 x(1) = 5 6 '[2,1]行列 7 y(0) = 4 8 y(1) = 5 9 10 Debug.Print (Mult(x(0),y(0))) 11

###試したこと

やむを得ないので、現状は以下のように読み込む配列を一つにし、行列Aには0~1の値、行列Bには2~3の値を入力するコードとしています。

c++

1double __stdcall Mult(double x[]) 2{ 3 4 MatrixXd z(1,1); 5 double z2[1]; 6 double z3; 7 8 MatrixXd A=MatrixXd::Ones(1,2); 9 MatrixXd B=MatrixXd::Ones(2,1); 10 11 A(0,0)=x[0]; 12 A(0,1)=x[1]; 13 B(0,0)=x[2]; 14 B(1,0)=x[3]; 15 16 z=A*B; 17 Map<MatrixXd>(&z2[0],1,1)=z; 18 z3=z2[0]; 19 20 return z3;

vba

1Private Declare Function Mult Lib "ExcelLink.dll" (x As Double) As Double 2 3 '[1,2]行列 4 x(0) = 3 5 x(1) = 5 6 '[2,1]行列 7 x(2) = 4 8 x(3) = 5 9 10 Debug.Print (Mult(x(0))) 11

このコードであれば、Matrix A、Bに正しく値を渡して計算することができます。

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

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

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

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

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

guest

回答2

0

自己解決

上記の件、お騒がせしてすみませんでした。
以下のサイトを参考にして作成し、解決いたしました。
http://stackoverflow.com/questions/19644876/how-to-pass-array-to-vba-from-a-c-dll

私のコードの問題点はC++のコード側にあったようです。
C++、VBA側の変更点は以下になります。

C++配列宣言:double x[] → double x
double __stdcall Mult(double
x, double* y)

VBAのDeclare文:
Private Declare Function Mult Lib "ExcelLink.dll" _
(ByRef x As Double, ByRef y As Double) As Double

VBAの入力コード:
Debug.Print (Mult(x(0), y(0)))

色々とご教授いただきましてありがとうございました。

投稿2016/08/26 23:48

cesolution

総合スコア217

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

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

0

VBA側のDeclare文がおかしいと思います。

VBA

1Private Declare Function Mult Lib "ExcelLink.dll" (ByRef x() As Double, ByRef y() As Double) As Double

じゃないとDLL側に配列を渡すことが出来ないと思います。

投稿2016/08/26 08:17

PineMatsu

総合スコア3579

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

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

cesolution

2016/08/26 08:27

PineMatsh様 早速のご回答ありがとうございます。 ご連絡いただいた方法でVBA側のDeclare分を変更してみたのですが、 「型が一致しません:配列またはユーザー定義型を指定してください」というエラーがでました。
episteme

2016/08/26 08:30

Multを*呼ぶ側*でちゃんと配列を渡してますか? # Mult(x(0),y(0)) じゃダメですよ?
PineMatsu

2016/08/26 08:35

「配列またはユーザー定義型を指定してください」ということは配列を渡していないということです。 Mult(x, y)で呼び出してくださいね。 x(0)は配列の最初の「値」を渡しているだけです。
cesolution

2016/08/26 11:31

PineMatsh様、episteme様 早速のご連絡ありがとうございます。 まさに、「Mult(x(0),y(0))」にしていました。 早速変更してみました所、エラーは解消されました! ただ、計算値が0となってしまいました。 現在先ほどまでとは異なるPCで検証しており、違う問題のようですので、一旦保留させていただきまして、また後ほど経過をご連絡させていただきます。 週明けになってしまうかもしれませんが、お許しいただければと思います。
cesolution

2016/08/26 12:35

上記の件、色々試してみましたが、どうもVBA側で指定したx,yの値がdll側に渡っていないようです。 VBA側で、 x(0) = 3、x(1) = 5、y(0)=4、y(1)=5とし、Debug.Print(Mult(x,y))を行い、dll側のreturnをのx[0]やy[0]にして確認してみましたが、出力は5.68...E-306等非常に小さい数値が入っているようです。 結果としてmatrix計算の出力をしても0が返ってきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問