情けない話ですがDLLの呼び出しで詰まっています。
TDataArray = array of array of Double;
~~~
procedure fft2D(n: integer; sr, si: TDataArray); stdcall;
external 'CppMathLibrary.dll';
これで関数fft2D()を呼び出したいのですがうまくいってません。XE7を使っています。DLL側の関数名は次のようなものです。
public: System:: Void fft2d(int n, Double sr[,],Double si[,])
{
}
そもそもvarを付けたらいいのかPDataArrayにしたものかわかりません。
Pointerで渡してみましたが依然エラーでアプリケーションが起動されません。
"dll array"で掲示板を検索してみたところ難しいということです
もう少し研鑽してみます。
DLL側の関数プロトタイプを正確に提示できますか?↑だと、
procedure fft2d(n: Integer; sr: PDouble; si: PDouble); ...
となると思いますが。で、呼び出し側は
var
n: Integer;
sr: array [0..9,0..9] of Double;
si: array [0..9,0..9] of Double;
begin
fft2d(n,@sr[0,0],@si[0,0]);
とかそういう呼び出しかたになるかと(要素数とかは適当)。第2,第3パラメータは結局連続して確保されたDoubleの領域の先頭アドレスを渡すことになります。
C++で作成されたほかの方のDLLを利用しています。
アプリケーション側での宣言は
sr, si: array of array of Double;
動的配列ですのでPDouble(si)とかになるのかなと思いました。伝達はうまくいっているでしょうか。
関数プロトタイプの部分をかみ砕いて説明していただくとありがたいです。
当初の説明に不正確さがあり回答者にはご迷惑をおかけしました。
現在もコンパイルは通るのですがダイアログが出てアプリケーションを起動できません。
今まで一度もDLLを利用したことがないので、原因の特定にはこの先も至らないかもしれません。
今回の趣旨であるDELPHIで配列型の引数を持つDLL関数が呼び出せるということがはっきりいたしましたので解決としたいと思います。
ご協力ありがとうございました。
メモリ管理の仕方が異なるので、Delphiの動的配列のarray of array of DoubleとCのdouble[,]は互換性がありません。
Delphi側は2次元の静的配列か、1次元の動的配列にして、パラメータにはその先頭要素のアドレスを指定してください。
>>現在もコンパイルは通るのですがダイアログが出てアプリケーションを起動できません。
引数の型やサイズが違っていても起動はしそうな感じですが
静的ファンクションコールのようですが「CppMathLibrary.dll」ファイルが無い
パスが通っていない、dllを置くにはふさわしくないフォルダにある
とかはありませんか?
take様、ご配慮ありがとうございます。
なぜか起動しないのです。現在はDELPHIで実装されたユニットから呼び出すことにしております。ファイル位置はアプリケーションと同じフォルダにありますので問題ないと思われます。
不正確な情報を追加いたしかねますのでご返事はこの辺にさせていただきますことをご了承ください。
心配ありがとう存じます。
今まで一度もDLLを利用したことがない、とのことなので、もしかして、
32bitアプリで64bitDLLの読み込み、またはその逆をしていませんか。
同一プロセスメモリ内に異なるアーキテクチャのモジュールを読み
込んで実行するのは、普通はできないと思います。
32bitか64bitかはPEヘッダで確認できます(DLL/EXEとも)
https://qiita.com/oyan29/items/1f0b5d227765115b24f0
この辺りが参考になると思います。
ご連絡ありがとうございます。
まさにエラーコードはご指摘の状況を返します。
リンク先の情報から調べてみたところ32bit-DLLでした。私はそのことも過去ログから察して32bitと64bitでコンパイルもしてみました。ですが状況は変わらなかったという報告をしておきます。
私が取り組んでいたのは2次元離散フーリエ級数変換を用いてパワースペクトルを表示させるプログラムでして、この先のことを考えるとフーリエ逆変換が用意されている本ライブラリを利用できると助かるのですが、引数の問題を解決できませんでした。
ただ、関数内で動的配列を利用するとはいえ、アプリケーション側が使用するコードを・・・制約となりますが静的配列で宣言してしまえば、まだあきらめなくてもよかったとは考えます。
でも私はよく考えました。この問題をひとまずC言語とDELPHI言語の間で調整したとしても、この先応用が利く話ではなくなる。そう思うのです。現在は別のサイトから拝借したDELPHI用ユニットにある1次元のフーリエ変換を活用しております。
>依然エラーでアプリケーションが起動されません。
なのですから,一般的に言えば,動的配列とか静的配列とかは関係ないと思いますよ.
アプリの起動時に DLL をロードして関数を実行するようになっていれば別ですが.
>なのですから,一般的に言えば,動的配列とか静的配列とかは関係ないと思いますよ.
DLL 内の関数を使用する場合,
引数のチェックが行われるのは,実際にその関数を実行する時です.
ですから,アプリの起動と同時に DLL 内のその関数を実行するのではない限り,
その関数の引数の数や型の違いが原因で,アプリが起動しないということはありません.
訂正です.
DLL 内の関数を使用する場合,
↓
DLL 内の関数を今回のような方法で使用する場合,
>その関数の引数の数や型の違いが原因で,アプリが起動しないということはありません.
ゴメンなさい.
型宣言して使用しているんですね.見落とししました.
型宣言している場合は型チェックが行われるので,
関数の実行部分のコードもコンパイル時にチェックされます.
>関数の実行部分のコードもコンパイル時にチェックされます.
いろいろ書いてしまつたので少し整理を.
具体的なコードがないと無理があるので以下のコードの場合.
引数が静的配列でも動的配列でも,
関数の内部処理が静的配列であろうと動的配列であろうとアプリは起動します.
type
// TDoubleDynArray の使用には uses に Types が必要
// これは array of array of Double と同じ
TDataArray = array of TDoubleDynArray;
procedure fft2D(n: integer; sr, si: TDataArray); stdcall;
external 'CppMathLibrary.dll';
procedure TForm1.Button1Click(Sender: TObject);
var
LSrcArray : TDataArray;
LDstArray : TDataArray;
LSize : Integer;
begin
// 配列のサイズを設定 (0 で初期化される)
LSize := 1024;
SetLength(LSrcArray, LSize, LSize);
SetLength(LDstArray, LSize, LSize);
// 関数の実行
fft2D(LSize, @LSrcArray, @LDstArray);
end;
上のコードで関数の実行部分を
fft2D(LSize, @LSrcArray);
とするとコンパイル時にエラーとなります.
また,引数の型が関数の宣言と違ってもコンパイル時にエラーとなります.
「アプリが起動しない」のとは違います.アプリが作成できないのです.
型宣言でない配列が引数の場合は,
引数の数や型が違っていてもコンパイルでき,アプリが起動します.
もちろん,静的配列とか動的配列であるとかは関係なくです.
ツイート | ![]() |