DLLファイルが読み込まれない?

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ジャーニー

DLLファイルが読み込まれない?

#1

投稿記事 by ジャーニー » 15年前

お久しぶりです

大学の研究でとあるハードウェアを使うことになり、その製品のライブラリを導入しようとしているのですがうまくいきません。
おそらくDLLが正常に読み込まれていないだろうと思います。

同梱ファイルの中身は単純で、使っているものの最低限の動作確認のため、初期化を実行しようとしているだけです。

test.cpp 
#include <iostream>
#include "DxLib.h"
#include "HAROC2D.hpp"

/* ドライバの初期化                                                        */ 
bool initializeDriver( void )
{
    int status;
    status = HAROC_InitDriver( 10+1 );      /* ドライバの初期化 */
    if( status != 0 ) {
        /* 初期化失敗処理 */
        return false;
    }
    else {
        /* 初期化成功処理 */
        return true;
    }
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
	if( !HAROC2manager::loadDLL() ) return 0;/* HAROC2.DLLのロード					  */
	if( !initializeDriver() ) return 0;

	HAROC2manager::freeDLL();			/* HAROC2.DLLの解放					  */

	return 0;
}
上のソースのHAROC_InitDriverでエラーがでており、エラーは
「Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.」
とでております。調べたところDLLを読み込んだあと正常に関数呼び出しだされていないのではないかという感じです。

hppファイルはDLLの読み込みと解放を記述しているだけです。
hppとDLLは製品に同梱されていたものです。
どなたかわかる方がいましたら回答をお願いします

御津凪

Re:DLLファイルが読み込まれない?

#2

投稿記事 by 御津凪 » 15年前

その DLL を使ったことが無いので正確ではないかもしれませんが、
そのようなランタイムエラーは 関数の呼び出し規約 が異なる場合に出ることがあります。

製品にマニュアルなどがある場合、何か呼び出し規約についての記述が無いか確かめてみてください。
基本、呼び出し規約の指定は、ヘッダ側の関数宣言でするものなのですが、指定がされていない場合、
コンパイラオプションで指定した呼び出し規約(VC++ なら通常は __cdecl)を指定することになります。

ジャーニー

Re:DLLファイルが読み込まれない?

#3

投稿記事 by ジャーニー » 15年前

このDLLは製品付属のものなので一般的にはないものです

呼び出し規約と決めるというのは初耳なのですが、どのように指定すればいいのでしょうか?

御津凪

Re:DLLファイルが読み込まれない?

#4

投稿記事 by 御津凪 » 15年前

VC++ の IDE であれば、
プロジェクトのプロパティから、「構成プロパティ」「C/C++」、「詳細」、「呼び出し規約」の順で設定にたどり着きます。
ここの設定を変更していって、DLL の関数を実行できるかどうかを確認していってみてください。
それぞれの呼び出し規約の機能については下記のページに書かれています。
http://msdn.microsoft.com/ja-jp/library/46t77ak2.aspx

なお、上記に書いたとおり、関数の宣言に呼び出し規約が指定されていたら設定を変更しても意味が無いので、
先にヘッダの該当する関数宣言の確認してください。
int <u>DLLDECL</u> dllfunc();
のように、戻り値の型と関数名の間に単語が入っていたらそれが呼び出し規約の指定です。
殆どの場合、マクロを使って指定しているので、元をたどればどんな呼び出し規約を指定しているかは確認できます。


ちなみに、今回発生しているランタイムエラーは、
「ESPの値が正しく関数呼び出しの間で保存されませんでした。
 これは、通常の関数呼び出しの結果は1つの関数ポインタで呼び出し規約を持つ別の呼び出し規約で宣言されたと宣言しました。」
(注:機械翻訳です)
となっています。
つまり、 ESP (スタックポインタ)が関数を呼び出した後、正しい位置に戻ってこなかったことを示しています。

ジャーニー

Re:DLLファイルが読み込まれない?

#5

投稿記事 by ジャーニー » 15年前

できました!ありがとうございます
_stdcallにすれば動きました

ただ別の問題が発生しました
このDLLをもうひとつDXライブラリで作っているプログラムに入れるのですが、ためしにそっちで_stdcallになおしたときDXライブラリの関数が未解決の外部シンボルとなってしまいます
御津凪さんのいわれているマクロを使えば大丈夫なのでしょうが、リンク先を見てみたのですがいまいちよくわからなかったです
簡単な例などあれば教えていただきたいのですがよろしいでしょうか

御津凪

Re:DLLファイルが読み込まれない?

#6

投稿記事 by 御津凪 » 15年前

DXライブラリの関数宣言群には、先述した呼び出し規約を明示的に指定していないので、コンパイラ側で変更した呼び出し規約で外部参照(シンボル)名が一致しなくなったのが原因ですね。
(呼び出し規約ごとに外部参照名が変化するため)

問題の発生していた DLL のヘッダにのみ正しい呼び出し規約を指定する必要が出たので、ヘッダを修正する必要がありますね。
呼び出し規約は関数宣言の戻り値と関数名の間に記述するので、対象ヘッダ内のすべての関数宣言に呼び出し規約を入れる必要があります。
この場合はただ単に、
int _stdcall dllfunc();
を入れていってもいいのですが、
後でもし何か問題があって、呼び出し規約を変えたい時にすぐ対応できるように、
#define MY_DECL _stdcall
と対象ヘッダの先頭あたりに記述し、
後は _stdcall の代わりに指定したマクロ名を入れていけば大丈夫です。
(マクロ名はDLLの名前などにしておくといいかもしれません)

あと、コンパイラの設定を元の設定に戻しておくのを忘れないでください。
「<親またはプロジェクトの既定値から継承>」でデフォルトに戻せます。

ジャーニー

Re:DLLファイルが読み込まれない?

#7

投稿記事 by ジャーニー » 15年前

詳しく回答していただきありがとうございます
ただ何度も申し訳ないのですが最初にアップロードしたhppファイルなのですが、ちょっと勉強不足でよくわからない方法で関数読み込みをしているため、そこでその方法を指定すればわからないのですがどのように指定すればいいのでしょうか

ジャーニー

Re:DLLファイルが読み込まれない?

#8

投稿記事 by ジャーニー » 15年前

ってすいませんアップロードしわすれていたみたいです
大変申し訳ありません
ちゃんと見直せばよかったです

hppファイルだけですがこちらになります

御津凪

Re:DLLファイルが読み込まれない?

#9

投稿記事 by 御津凪 » 15年前

今回の場合であれば、 HAROC2D.hpp の中にある関数宣言文を対象に行えばいいのではないでしょうか。
恐らくそれだけで済むかと思います。
(HAROC2D.hpp の中に HAROC2 の他のヘッダをインクルードされていたらそれも対象に行ってください)

御津凪

Re:DLLファイルが読み込まれない?

#10

投稿記事 by 御津凪 » 15年前

添付していただいたヘッダの場合だと、
/* API関数型定義 */
の中の typedef 群ですね。
typedef int  ( *THAROC_InitDriver )( int );
のような感じになっている所を、
typedef int  (_stdcall *THAROC_InitDriver )( int );
のように入れていけばOKです。

ジャーニー

Re:DLLファイルが読み込まれない?

#11

投稿記事 by ジャーニー » 15年前

今教えていただいた方法でやってみました

呼び出し規約を親またはプロジェクトから継承にし、

#define MY_DCEL _stdcall




typedef int (MY_DCEL *THAROC_InitDriver )( int );

のように変更してみたのですがESPがまた出てしまいました

プロジェクトファイルをあげようとしたのですがファイル制限をこえてしまったためソースのみあげさせていただきます
ただDLLファイルがどう圧縮しても120KB制限にひっかかったためアップロードできないみたいです
若干の改変(ヘッダファイルの移動くらいですが)を行ったものです
おそらく私が変なことをしただけだと思うのですが・・・
何度も質問してしまいお手数をおかけしますがよろしくお願いします

御津凪

Re:DLLファイルが読み込まれない?

#12

投稿記事 by 御津凪 » 15年前

コード自体にはそれらしいミスが無いので、実際に DLL を読み込んで試さないとわかりませんね…。
DLLを圧縮したものを下記のメルアドに送ってもらえませんか?
mitsunagistudio@gmail.com
(解決した後、受け取ったファイルは破棄いたします)

ジャーニー

Re:DLLファイルが読み込まれない?

#13

投稿記事 by ジャーニー » 15年前

DLLファイルを送らせていただきました
お手数ですがよろしくお願いします

御津凪

Re:DLLファイルが読み込まれない?

#14

投稿記事 by 御津凪 » 15年前

さっそく受け取り、確認してみました。

結果はエラーが発生しませんでした。
(_stdcall を外して試すときちんとランタイムエラーが出ました)

エラーが出るということはきちんとビルドされていないのかもしれません。
リビルドして確かめてみましたか?

ジャーニー

Re:DLLファイルが読み込まれない?

#15

投稿記事 by ジャーニー » 15年前

ソリューションのクリーンを行い、最初からビルドしてみましたが無理でした
エラーがでなかったということで、もう一度試してみたのですがやはりESPがでてしまいました
もしかするとプロジェクトの設定がまずかったのかもしれませんので、上記のアドレスにプロジェクトごと送らせていただいたので確認していただいてもよろしいでしょうか

御津凪

Re:DLLファイルが読み込まれない?

#16

投稿記事 by 御津凪 » 15年前

すいません。届いていないみたいです。
再度お願いできますか?
(圧縮したほうがいいです)

ジャーニー

Re:DLLファイルが読み込まれない?

#17

投稿記事 by ジャーニー » 15年前

すいません途中でエラーがでてしまっていたみたいです
今送信完了しました

御津凪

Re:DLLファイルが読み込まれない?

#18

投稿記事 by 御津凪 » 15年前

エラーの原因を捕捉しました。
test.cpp では、
#include "../../../HAROCLIB/HAROC2D.hpp"
のファイルをインクルードしていますが、
変更を加えたヘッダファイルはこれではないので、エラーが出ます。

これを修正したヘッダファイルをインクルードするように直せばうまくいくはずです。

ジャーニー

Re:DLLファイルが読み込まれない?

#19

投稿記事 by ジャーニー » 15年前

今確認したところ完全に間違えていましたorz
人間の思い込みって怖いですね

夜分遅くまでこのような質問にお答えいただいてありがとうございました
御津凪さんのサイトにもたくさんおもしろそうなものがありましたので参考にさせていただきます
ありがとうございました

御津凪

Re:DLLファイルが読み込まれない?

#20

投稿記事 by 御津凪 » 15年前

それでは解決したそうなので、メールにて受け取った各メール・ファイルは破棄しておきます。

あと、解決した場合は解決マークを付けてくださいね。(ニアミスでした)

ジャーニー

Re:DLLファイルが読み込まれない?

#21

投稿記事 by ジャーニー » 15年前

解決にし忘れていました

閉鎖

“C言語何でも質問掲示板” へ戻る