新しく発言する EXIT インデックスへ
DLL利用について

  DLL利用について 加藤 2005/11/24 16:26:23 
  DLLを利用する場合の基本的な注意事項は,誤... 白石 和夫 2005/11/24 18:14:55 
   └さっそくの回答ありがとうございます。 加藤 2005/11/24 19:01:22 
    └Cで8ビット無符号数を扱うのであれば,通常... 白石 和夫 2005/11/24 20:51:38 

  DLL利用について 加藤 2005/11/24 16:26:23  ツリーへ

DLL利用について 返事を書く
加藤 2005/11/24 16:26:23
とても使いやすいので、すっかり十進BASICのファンになっています。
今、ビットマップファイルを読み込んでその画像を表示するソフトを作成したのですが、次のステップとして動画表示を考えています。そこでは、ファイルのオープン、ヘッダファイルの読み込み、ピクセルデータの配列への格納は十進BASICで行い、画像描写はC言語(BorlandのC++)でDLLとして組むことを予定でいます。そこでまず、十進BASICのFAQの「Win32APIとDLLの利用」を読んで、事前学習をしたのですが、本当に自分が理解しているか疑問になり、掲示板に書き込みさせて頂きました。ちなみにCは初心者レベルです。

ピクセルデータ(8ビット、符号なしでグレートーン)はBASIC上で例えば、A(x、y)という風に格納されていて、DDLへの引数として、その配列Aの先頭番地(ポインタ)を渡すとするとき、
DECLARE EXTERNAL FUNCTION DrawBmp
DECLARE EXTERNAL FUNCTION FndWnd
LET hWnd=FndWnd("TPaintForm","")
LET s$=CHR$(A(0,0))
LET n=DrawBmp(hWnd,s$)  //固定サイス゛、位置に画像描画するDLL
END
EXTERNAL FUNCTION DrawBmp(s$)
ASSIGN "MyDll.dll"、"DrawBmp"
END FUNCTION
EXTERNAL FUNCTION FndWnd(lpClassName$,lpWindowName$)
ASSIGN "user32.dll","FindWindowA"
END FUNCTION
(DLL関数の宣言、ファイルオープン、ヘッダ読み込み、ピクセルデータの配列への格納部分は割愛しました)

また、C側(DLL”MyDll")では
_declspec(dllexport) int _stdcall DrawBmp(CDC hDC,unsigned int *a)
{
int i,j;
for(i=0;i<100;i++){
for(j=0;j<100;j++){
SetPixel(hDC,j,i,RGB(a[j][i],a[j][i],a[j][i]));
}
}
return;
}
で良いのでしょうか?

実際にやってみてからメールしても良かったのですが、初めてやってみること(DLL)が多く、エラーメッセージに追いまくられてパニクるのが恐く、書き込みをしてしまいました。よろしくお願いします。

  DLLを利用する場合の基本的な注意事項は,誤... 白石 和夫 2005/11/24 18:14:55  ツリーへ

Re: DLL利用について 返事を書く
白石 和夫 2005/11/24 18:14:55
DLLを利用する場合の基本的な注意事項は,誤りがエラーメッセージの形では検出されないことです。間違ったことを実行してもその指示の通りに動きます。エラーメッセージに追いまくられることはありませんが,それ以上に深刻な事態が起こるかも知れないことを予期しておく必要があります。
BASICの数値配列は,Cの整数型の配列(というかどうかくわしいことは知りませんが)とは互換性がありません。BASICの数値変数のアドレスをDLLの関数に渡して処理することは,(仮にそれが実行できたとしても)実際上,不可能です。
なお,LET s$=CHR$(A(0,0)) でS$に入るのは,Aのアドレスではなく,単にA(0,0)の数値に対応する文字に過ぎません。
C言語での整数型の数値配列のメモリ上での配置は確定しているので,BASICの側でC言語での整数型配列に必要なサイズのメモリを文字列変数の名目で確保し,そのアドレスをDLL関数に渡すのが普通です。ただし,メモリ確保をDLLの側で行う方法もあります。
BASICの側では,C言語での配列要素のメモリ上の配置にしたがって,バイト列を操作してデータを書き込みます。
このとき,OPTION CHARACTER BYTEの宣言が不可欠です。

   └さっそくの回答ありがとうございます。 加藤 2005/11/24 19:01:22  ツリーへ

Re: DLLを利用する場合の基本的な注意事項は,誤... 返事を書く
加藤 2005/11/24 19:01:22
さっそくの回答ありがとうございます。
「BASICの側でC言語での整数型配列に必要なサイズのメモリを文字列変数の名目で確保し,そのアドレスをDLL関数に渡す」というのは、例えばピクセルデータが100×100バイトあるとすると、s$=Repeat(" ",100*100)とすることで「整数型配列に必要なサイズのメモリを文字列変数の名目で確保」かなと思ったり、その後の「BASICの側では,C言語での配列要素のメモリ上の配置にしたがって,バイト列を操作してデータを書き込みます」の文書から、
For i=0 to 100
For j=0 to 100
s$=s$+chr$(A(j,i))
next j
next i
かなと思ったりと、まだ良くわかっていません。
また、そのアドレスをどのようにして得て、DDLに渡すのかを具体的にお教え願えればと思います。よろしくお願いいたします。

    └Cで8ビット無符号数を扱うのであれば,通常... 白石 和夫 2005/11/24 20:51:38  ツリーへ

Re: さっそくの回答ありがとうございます。 返事を書く
白石 和夫 2005/11/24 20:51:38
Cで8ビット無符号数を扱うのであれば,通常はint型でなく,char型を使うと思います。
C言語では,配列値をポインタを介して処理するようにして,そのポインタにBASICで確保した文字列変数の先頭アドレスを代入します。
BASICの文字列中では,OPTION CHRACTER BYTEを宣言した状態のとき,文字列中の位置とバイト単位での位置とが一致します。

C言語でchar型の配列として宣言された変数に対してa[i][j]のように書いたときにそれがaの先頭から何バイト目になるかはC言語では明確に規定されていると思います。それが,
For i=0 to 100
For j=0 to 100
s$=s$+chr$(A(j,i))
next j
next i
でよいのかどうかは,C言語の文献を調べないと分かりません(調べてください)
s$=s$+chr$(A(j,i))はマイクロソフトの文法なので,修正が必要です。
十進BASICでは,文字列変数の実領域は動的に変化します。
For i=0 to 100
For j=0 to 100
s$=s$+chr$(A(j,i))
next j
next i
にょうな文を実行すると,s$=s$+chr$(A(j,i))を実行するごとに変数の実領域が変化します。しかし,それが完成した時点では必要なメモリは確保されています。
この場合,最初にs$=Repeat(" ",100*100)を実行するのは無駄です。


インデックスへ EXIT
新規発言を反映させるにはブラウザの更新ボタンを押してください。