2010-12-13 7 views
4

私の質問は少し一般的であるので、私は正確な答えを探していないんだけど、多分それに見て、いくつかの方向性が私を助ける...C#DLLIMPORTトラブル

C#。 私たちは、このサードパーティーの会社と協力して、使用する必要があるネイティブC++ DLLを提供しました。 私が必要としたC++メソッドはC#から参照しやすい方法で公開されていなかったので、別のネイティブC++ Dllでdllをラップしました。

私は2つのネイティブC++ dllを持っています.1つはもう一方をラップしています。

私はC++で作成したメソッドを呼び出す小さなC#コンソールアプリケーションを作成しました。 私のメソッドのシグネチャは次のようになります。私のコンソールアプリケーションで

[DllImport("HashMethodWrapper.dll")] 
[return: MarshalAs(UnmanagedType.LPStr)] 
private static extern string CreateHash(
      string input, 
      [MarshalAs(UnmanagedType.LPStr)]StringBuilder output); 

、すべてが正常に動作し、私はいつも、結果に期待した文字列イムを受けます。

私はそれを私が実際に必要とする場所なので、作成したWebサービスまたはWebアプリケーションに移動すると、受信した文字列がガベージであり、一貫していないことがわかります。それは失われたメモリなどの参照を取得しているようですが、これは唯一の推測です...

私のコンソールアプリケーションではすべてが動作するので良い。

は誰も私を助けるかもしれない方向を持っています??? ...事前に

おかげで、 gillyb

編集:私はそれはいくつかの固定されていないオブジェクトとしなければならないかもしれないと思っ 、だから私は固定ステートメントのようなものを呼び出すことを試みた:

...しかしこれはまだ私のためにそれをしなかった。これはオブジェクトを固定する正しい方法ですか?

第二編集:私は

extern "C" __declspec(dllexport) bool CreateRsaHash(char *inputPass, char *hashPass); 

とするメソッドのシグネチャを変更し

extern "C" __declspec(dllexport) char *CreateRsaHash(char *inputPass, char *hashPass); 

第三編集: C++でのメソッドのシグネチャは次のようになります探している戻り値は*hashPassパラメータに格納されます。

ここでは、簡単なコンソールアプリケーションを作成してテストしました。メインクラスにDllImportを挿入し、メソッドを直接呼び出すとすべてがうまく動作しますが、DllImportを移動して別のクラスにメソッドをラップし、そのクラスをConsoleの「Main」メソッドから呼び出すと、StackOverflow例外が発生します。

誰もがこれが起こっている理由を知りましたか?

+0

C/C++での関数ヘッダーの宣言方法を教えてください。それは助けることができる:) –

+0

APIの著者を殺す、非常に明確なメモリリークが起こっている... – leppie

+0

なぜ???あなたは理由を説明してください、なぜそれが署名からとても明らかであるのですか?うまくいけば、私たちはまだそれを修正することができます! – gillyb

答えて

0

私は私の問題の解決策を見つけましたが、今私はちょっと気分が悪いと感じます。

C++でLoadLibrary()メソッドを使用して、他のネイティブDLLからメソッドを動的に呼び出すようにしました。問題は、メソッドにパスを与えず、dllファイル名だけを渡すことでした。ネットでは、現在のフォルダを検索してしまいましたが、ネイティブコードのように思えますが、これはこのようには動作しません。

私のプログラミングのより大きな問題は、明らかに、私がネイティブのC++ dllでエラー処理を完全にカバーしていなかったことです。私は、ディレクトリ・パスに問題があったことが判明

たら、私はこのページに受信

すべてasnwersは何もありませんでしたけれども...、私は壊れたメモリにアクセスしようとしている程度異なる例外に走りました、そして、私は固定されたオブジェクトを作成し、私のStringBuilderオブジェクトのサイズを宣言する必要がありました。

皆様のおかげでよろしくお願いいたします。

:)

+0

ニース。よくやった。 –

1

疎な情報から本当に知るのは難しいですが、私が推測しなければならないのは、出力オブジェクトを確実に固定する必要があると言います。また、おそらく出力パラメータを他のいくつかの型に変更すると、StringBuilderが正直に動作するのはかなり奇妙なようです。

オブジェクトを割り当てると、ポインタが取得されますが、それは移動しないことを意味するわけではありません。したがって、マネージドオブジェクトへのポインタをアンマネージド環境に渡そうとすると、GCがメモリを「ピン」して、あなたの下から移動しないようにする必要があります。ここで

は、私が固定することによって何を意味するかの本当にラフなバージョンです:

string input = "..."; 
StringBuilder output = new StringBuilder(); 
var handle = System.Runtime.InteropServices.GCHandle.Alloc(output, GCHandleType.Pinned); 
try 
{ 
    CreateHash(input, output); 
} 
finally 
{ 
    handle.Free(); 
} 
+0

まあ、StringBuilderについては、 'String'は不変で、この場合は仕事をしないので、値が変わるとstringbuilderが必要になると私はどこか読んでいます。これは本当ですか ? – gillyb

+0

そしてピン留めされたオブジェクトについて、私はそれが問題かもしれないと思ったので、私はいくつかのピン留めをしようとしました。私は私の質問にそれを追加します、あなたは私が何をしたのか、GCHandle.Allocで私に示したものの違いは何か教えてください。 – gillyb

+0

2つのこと:char *を固定しましたが、StringBuilderは固定しませんでした。また、なぜあなたは '出力'と戻り値と呼ばれるStringBuilderを持っていますか?あなたはStringBuilderを完全に無視して戻り値を返すようです。 –

0

私が代わりにC++のdllのC#共有アセンブリ/ DLL内でワープし、その後に、コンソールアプリケーションを取得しようとする検討しますdllで作業してください。いずれにしても、このように外部依存関係をラップすることをお勧めします。
それ以外の場合、いくつかの従来の問題は、32ビットと64ビットの共有ライブラリへのロードパスです。それは本当に文字列かもっと複雑なものですか?