VCで作ったdllをVBで実行すると

解決


黒田  2005-09-04 08:56:08  No: 58844

こんばんは.
現在,VCでdllを作成し,VBでそれを動かしています.
ところが,dllを動かしたあとにプログラムが終了してしまいます.
エラーなど出ていないのにです.

dllではVBで受け取ったデータを元に計算を行い,それをfprintfで出力しています.
出力されたファイルを見る限り思い通りの計算はできているのですが・・・.
誰か原因が分かる方アドバイスください.
環境はVB,VCともに6.0,Win2000です


Blue  2005-09-04 09:47:08  No: 58845

VC、VB共にどのように関数を宣言しているか書いてくれますか?


黒田  2005-09-04 10:40:09  No: 58846

VC++(dll側は)
_declspec(dllexport) short _stdcall AveBrightMain(HDC hDC,char *filename)
VB
Private Declare Function AveBrightMain Lib "D:\vc\Testdll\Debug\Testdll.dll" (ByVal hDC As Long, ByVal filaname As String) As Integer
です.よろしくお願いします.


Blue  2005-09-04 10:46:47  No: 58847

両方のデバッグできるように、
仮にVBでexeを作成し、VCでデバッグ用プログラムをVBで作成したexeを指定し、
デバッグしてみてはどうでしょうか?

> ところが,dllを動かしたあとにプログラムが終了してしまいます.
だと、VC側で落ちている可能性が高いかと。


黒田  2005-09-04 12:12:01  No: 58848

素早い返答大変ありがとうございます.

確かにdll側みたいです.
デバッグすると↓のようになりました.
例外処理 (初回) は Project1.exe にあります: 0xC0000005: Access Violation。
しかし,ステップインさせていくと,全部のコードが終わった後にエラーが出ています.ので???な感じです.とりあえず,もう少し考えています.


Blue  2005-09-04 12:44:45  No: 58849

> 全部のコードが終わった後にエラーが出ています
デストラクタかなんかかなぁ。。。

具体的にソースが載せれるならば、載せれていただけるとうれしいです。


黒田  2005-09-04 13:12:52  No: 58850

大変お世話になります.
プログラムとしては[画像ファイルのパスが書いてあるデータ]を読み込んで,
画像の輝度値の平均値を順に出力するプログラムとなっています.
データは次のような感じです
520.bmp
110.bmp
210.bmp

ソースは次のような感じです
_declspec(dllexport) void _stdcall AveBrightMain(HDC hDC,char *filename){
char image_in[Y_SIZE][X_SIZE][3];  // 入力カラー画像配列
  FILE *fp1,*fp2;
  char s[256];
  int len,avebright;
  if ((fp1 = fopen(filename, "r")) == NULL) {
    TextOut(hDC,10,10,"r file open error!!",17);
    exit(1);  
  }
  if ((fp2 = fopen("kekka.txt", "w")) == NULL) {
    TextOut(hDC,10,10,"w file open error!!",17);
    exit(1);  
  }

/*平均値ファイル出力*/

  /* (4)ファイルの読み(書き)*/
  
  while (fgets(s, 256, fp1) != NULL) {
    len=strlen(s);
    if(s[len-1]=='\n'){
      s[len-1]='\0';
    }
    
    readBMP(s, image_in);        
    avebright=AveBrightness(image_in);
      fprintf(fp2,"%d\n",avebright);
  }
  fclose(fp1);
  fclose(fp2);
}


とおり  2005-09-04 22:26:10  No: 58851

>> 全部のコードが終わった後にエラーが出ています
>デストラクタかなんかかなぁ。。。

全部のコードの後ということは、Blueさんの言うように、(例えば)global変数オブジェクト
のデストラクタで不正アドレス参照とかの可能性があるので、↑のコードだけでは何とも
言えないと思いますよ。
かと言って「ここを示せ」とはっきり言える状況でもないわけですが。

# でも、CRTにしろMFCにしろ、デバッグモードならデストラクタとかもステップ実行
# されませんかね…??

一応、問題をはっきり切り分けるために、VBからではなく、dllの利用側もVCにして再現
するかを確認するという手はあると思います。
これで、VBは完全に無関係と切り分けられるかと。


Blue  2005-09-05 00:19:35  No: 58852

直接関係ないけど、
>    if ((fp1 = fopen(filename, "r")) == NULL) {
>        TextOut(hDC,10,10,"r file open error!!",17);
>        exit(1);    
>    }
BeginPaint関数で、文字を描くよというふうに宣言しなくてもいいのでしょか。。。

私ですと、
> _declspec(dllexport) void _stdcall AveBrightMain(HDC hDC,char *filename){
ではなくて、
_declspec(dllexport) HRESULT _stdcall AveBrightMain( LPCSTR filename )
にして、戻り値としてどんなエラーがあったかを返すほうがいいかと思います。
メッセージが動的に変わるのならば、
_declspec(dllexport) HRESULT _stdcall AveBrightMain( LPCSTR filename, LPCSTR errormsg )
または
_declspec(dllexport) HRESULT _stdcall AveBrightMain( LPCSTR filename, VARIANT* errormsg )
みたいにします。

細かいですが、
>       len=strlen(s);
>       if(s[len-1]=='\n'){
>           s[len-1]='\0';
>       }
len == 0 の場合これだとよろしくなさそうなので、
char* nl = strchr( s, '\n' );
if ( nl ) n1 = '\0';
のようにしたほうがいいです。

> 一応、問題をはっきり切り分けるために、VBからではなく、dllの利用側もVCにして再現
> するかを確認するという手はあると思います。
には賛成です。


Blue  2005-09-05 00:21:41  No: 58853

typo    orz
> if ( nl ) n1 = '\0';
if ( nl ) nl = '\0';


Blue  2005-09-05 00:28:33  No: 58854

また間違えてる。。。 ( ´△`)アァー
> if ( nl ) nl = '\0';
if ( nl ) *nl = '\0';


Blue  2005-09-06 10:24:21  No: 58855

訂正
> _declspec(dllexport) HRESULT _stdcall AveBrightMain( LPCSTR filename, LPCSTR errormsg )
>または
>_declspec(dllexport) HRESULT _stdcall AveBrightMain( LPCSTR filename, VARIANT* errormsg )
_declspec(dllexport) HRESULT _stdcall AveBrightMain( LPCSTR filename, LPSTR errormsg )
または
_declspec(dllexport) HRESULT _stdcall AveBrightMain( LPCSTR filename, VARIANT* errormsg )
または
_declspec(dllexport) HRESULT _stdcall AveBrightMain( LPCSTR filename, BSTR* errormsg )


黒田  2005-09-06 23:01:23  No: 58856

みなさん丁寧なレスありがとうございます.
ちょっと忙しいのでVC++でdll動かすのは明日になりそうです.
逃げてるわけではないのでご了承を.


kuroda  2005-09-10 00:11:13  No: 58857

返事遅くなりました.
まず,ソースのアドバイスありがとうございます.

で,肝心の結果なのですが・・・.
何度も試しているうちに勝手に解決してしまいました.
ただ,VC++で動かしたときとVBで動かしたときの動作が異なっていました.

ただ,char image_in[Y_SIZE][X_SIZE][3];がグローバルにしたときにうまくいったのでこの変の理解が足りてなかったのかも知れません・・.


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加