2009-11-24 7 views
10

私はC++ APIでいくつかの関数を呼び出すC#アプリケーションを少し書いています。私はC++コードをDLLに組み込み、C#コードはDllImportを使ってAPIを呼び出します。でC#のC++:C++関数(DLL内)がfalseを返すが、C#はそれが本当だと思う!

bool Foo() 
{ 
    return false; 
} 

:(。私は、私はにextern「C」を必要としないC++ DLLの.defファイルを使用しています)

をこれまでのところ、APIは現在、絶対に何もしない1つの機能を有していますC#の、私は次のようしている:

public class FooAPI 
{ 
    [DllImport("Foo.dll")] 
    public static extern bool Foo(); 
} 

... 

bool b = FooAPI.Foo(); 
if (!b) 
{ 
    // Throw an exception 
} 

私の問題は、何らかの理由で、bは常にTRUEに評価している、ということです。 if(!b)にブレークポイントがあり、デバッガはC++関数が返すものとは無関係に 'true'と報告します。

C#boolはC++ boolと同じですか?たとえこれが当てはまらないとしても、戻り値が「真」であることをどうして得られるかはまだ分かりません:)

この奇妙な矛盾は誰でも助けてくれますか?

ありがとうございます!

+0

あなたは真のC++関数の戻り値を持っている場合は、あなたのC#メソッドは戻り値として何を参照するのでしょうか? –

+0

FooAPI.Foo()メソッドを使用するコードを教えてください。 – Kevin

+1

C++関数をextern "C"と宣言してはいけませんか? –

答えて

15

お試し[return: MarshalAs (UnmanagedType.I1)]デフォルトでは、C#boolは1バイトのAFAIRですが、intと同じC#interop marshals C# bool as the Win32 BOOLです。したがって、C#のデフォルトマーシャリングでは、戻り値がeaxレジスタのBOOLであると予想され、C++ boolalに返されるため、ゼロ以外のガベージが取得されます。

+0

ありがとうございます。それははるかに理にかなっています。代わりにブール値を使用してトリックをしました。 –

2

投稿されたコードスニペットは機能しません。これがC++コンパイラでコンパイルされた場合、関数名は?Foo @@ YA_NXZとなり、C#コードではそれを見つけることができませんでした。呼び出し規約も重要です。コンパイラに通知しない限り、デフォルト(CallingConvention.StdCall)ではありません。そしてどこかでリンカに関数をエクスポートするように指示しておいたはずです。それはデフォルトのP /呼び出しと互換性がありますので、エクスポートされた関数を宣言することによって

スタート属性:

extern "C" __declspec(dllexport) 
bool __stdcall Foo() { 
    return false; 
} 

次の問題は、C++コンパイラはブール値を格納する1バイトのみを使用していることです。あなたのreturn文のために生成されたマシンコードは次のとおりです。

013D138E xor   al,al 

P /起動マーシャラーは、しかし、それは32ビットの整数であると仮定し、EAXレジスタの値をチェックします。関数の戻り値の型をintまたはBOOLとして宣言するか、C#宣言で[return:MarshalAs(UnmanagedType.U1)]属性を使用してください。

+0

申し訳ありませんが、extern "C"の代わりに.DEFファイルを使用しています。元の投稿を編集します。これが当てはまらなかった場合、C#は「EntryPointが足りない」と不平を言うでしょう。 –

0

を使用しました。

C++コード

extern "C" __declspec(dllexport) signed int TestDouble(double* output) 
    { 
     *output = 1.3; 
     return true; 
    } 

C#コード

[DllImport("abc.dll", EntryPoint = "TestDouble", CallingConvention = CallingConvention.Cdecl)] 
public static extern bool TestDouble(out double output); 
関連する問題