8

C#コードから呼び出したいC++dllを作成しました。1つの関数を呼び出すことはできますが、C#コードがdllを読み込もうとすると、もう1つの関数が例外をスローします。

ヘッダーは次のようになります。

extern "C" __declspec(dllexport) BOOL Install();
extern "C" __declspec(dllexport) BOOL PPPConnect();

これにより、エクスポートテーブルが少しわかりにくいdllが生成されます(名前フィールドでfoo = fooはどういう意味ですか?):

File Type: DLL

Section contains the following exports for PPPManager.dll

00000000 characteristics
499F44F0 time date stamp Fri Feb 20 16:04:00 2009
    0.00 version
       1 ordinal base
       2 number of functions
       2 number of names

ordinal hint RVA      name

      1    0 000078E4 Install = Install
      2    1 000079DC PPPConnect = PPPConnect

私のP/Invoke宣言は次のようになります。

[DllImport("PPPManager.dll")]
private static extern bool Install();

[DllImport("PPPManager.dll")]
private static extern bool PPPConnect();

Installの呼び出しは例外なく返されますが、PPPConnectを呼び出すと、MissingMethodExceptionが発生します-「PInvokeDLL'PPPManager.dll'にエントリポイント'PPPConnect'が見つかりません。」

Install関数宣言からexternおよびdeclspecディレクティブを削除しようとしました。これにより、エクスポートされる関数はPPPConnectだけになりますが、それでもPPPConnectを呼び出すことはできません。

また、序数でDllImportを実行してみました。これにより、名前で呼び出すのと同じ結果が得られます。Installは戻りますが、PPPConnectは「エントリポイント'#2'が見つかりません...」という例外をスローします。

相互運用ログは次のようになります。

[pinvokeimpl][preservesig]
bool  invivodata.Common.System.IPAQUtils::Install();
BOOLEAN (I1_WINBOOL_VAL) Install();

JIT ERROR FOR PINVOKE METHOD (Managed -> Native): 
[pinvokeimpl][preservesig]
bool  invivodata.Common.System.IPAQUtils::PPPConnect();
BOOLEAN (I1_WINBOOL_VAL) PPPConnect();

これは私の専門分野から大きく外れているので、どんな提案や考えも歓迎します。

ありがとう、ポール

編集:このコードは機能することがわかりました。問題は、最新のdllがデバイスに伝播されないことでした。D'oh!

4

5 に答える 5

8

これらの関数をエクスポートするためにdllプロジェクトで.defファイルを使用していますか?その場合は、それを削除して再試行してください。extern "C" declspec(dllexports)を実行すると、エクスポートが本来あるべきものではないように見えるため、これは単なる推測です。

私はこれを使用して単純なC++dllで試してみました

extern "C" __declspec(dllexport) BOOL Install();
extern "C" __declspec(dllexport) BOOL PPPConnect();

PInvoke宣言を使用した単純なC#アプリで、正常に機能しました。

私が見たdllでdumpbin/exportsを実行したとき:

ファイルPPPManager.dllのダンプ

ファイルの種類:DLL

セクションには、PPPManager.dllの次のエクスポートが含まれています

00000000 characteristics
499F6C2D time date stamp Fri Feb 20 20:51:25 2009
    0.00 version
       1 ordinal base
       2 number of functions
       2 number of names

ordinal hint RVA      name

      1    0 000110CD Install = @ILT+200(_Install)
      2    1 00011069 PPPConnect = @ILT+100(_PPPConnect)

私の場合、エクスポートされた名前が異なることに注意してください。

于 2009-02-21T02:51:05.707 に答える
1

あなたの説明によると、Install と PPPConnect は名前だけが異なります。C# アプリケーションで古い .dll バージョンを使用しているだけだと思います。PPPConnect が定義されていないもの。

宣言は正しいように見えます(情報源なしで判断できる限り)。

于 2009-02-21T02:12:17.483 に答える
1

PPPConnectOS によって誤解される方法で失敗するのと同じくらい簡単なことかもしれません。Installと の両方をPPPConnectno-ops (TRUE他に何もせずに返すだけ)として実装してみて、エラーが続くかどうかを確認してください。その場合は、それらがエクスポートされる順序を入れ替えてみて (まだノーオペレーションのまま)、問題が順序付けに関連しているのか (可能性は低い)、それとも他の何かに関連しているのかを確認してください。

グラフィカル ツールdependsを使用して、DLL のエクスポート テーブルがどのように表示されるかを確認することもできますが、問題がそれらの部分にあるとは思えません。

于 2009-02-21T02:00:18.027 に答える
0

依存関係ウォーカーを使用して DLL を開いて、使用可能なメソッドを確認します

于 2009-03-27T15:02:06.803 に答える
0

素晴らしい情報ですが、あなたが言及したように、ここではすべてが整っています。Windows 用のデバッグ ツールをインストールして実行してみてください。

kd -z \path\to\PPPManager.dll -y \path\to\PPPManager.pdb -c "x pppmodule!*"

シンボル テーブルのより良いダンプを取得します。これもブラインド ショットですが、次のことも試してみてください。

extern "C" 
{
    __declspec(dllexport) BOOL Install();
    __declspec(dllexport) BOOL PPPConnect();
};

__declspec が奇妙なことをしている場合。

于 2009-02-21T01:59:04.753 に答える