2011-06-21 7 views
1

を渡して管理されていないC++の関数を呼び出す:ここC#の - 私は私のマネージコードから次の関数を呼び出したいLPVARIANT

short LS_LoadConfig(LS_ID SensorID,LPVARIANT varConfigPathFile,BOOL bInit) 

は、私は私のC#クラス内でextern関数を宣言する方法である:

[DllImport("LineSensor.dll", EntryPoint = "#16")] 
private static extern Int16 LS_LoadConfig(
     Int16 deviceId, 
     IntPtr variantFilePath, 
     int init); 

そして、ここで私はどのようにVARIANTインスタンスを作成し、それへのポインタを取得します。その後、私はC#の関数を呼び出す:

string filepath = @"C:\Windows\ ..."; 
IntPtr variantFilePath = Marshal.AllocCoTaskMem(200); 
Marshal.GetNativeVariantForObject(filepath, variantFilePath); 
LS_LoadConfig(device.Id, variantFilePath, initLineSensor); 

問題は、私のようなエラーメッセージを受信し続けることである「LS_LoadConfig関数を呼び出すと、パラメータが管理されていない署名と一致していることを確認し、アンバランスなスタックを持っています」。

問題は、第2引数 "variantFilePath"が適切にマーシャリングされておらず、管理されていないヒープ上のサイズがアドレス(私の場合は32ビット) 。私は次のようにintにのIntPtrからC#関数のシグネチャでタイプを変更しようとしました:

[DllImport("LineSensor.dll", EntryPoint = "#16")] 
    private static extern Int16 LS_LoadConfig(
     Int16 deviceId, 
     int variantFilePath, 
     int init); 

私は乱数を渡す関数を呼び出ししようとしましたが、それは少し良くなった、私はちょうどエラー「メモリアクセスを受けています違反"。明らかに乱数は有効なアドレスではなかったためです。

誰でもこの問題の解決策を知っていますか?

ありがとうございました。

答えて

0

"LS_LoadConfig関数を呼び出すと、スタックのアンバランスが発生し、そのパラメータがアンマネージシグネチャと一致するかどうかを確認します"。

これは、通常、ネイティブコードとマネージコードの間で競合する呼び出し規約を使用していることを意味します。 C#はデフォルトでstdcallを使用し、c/C++はcdeclを使用します。 CallingConvention = CallingConvention.Cdeclを指定してみてください。

+0

問題は、Cdeclに設定する必要がある呼び出し規約でした。したがって、[DllImport( "LineSensor.dll"、EntryPoint = "#16"、CallingConvention = CallingConvention.Cdecl)]はすべてを修正しました。 @Hansまた、refオブジェクトを渡すことはLPVARIANTを渡すことと同じですが、私の解決策よりもエレガントです。 – kean

+0

@Kean喜んで私は助けることができました。 –

1

作成したアクセス違反は良くありません。また、MDA警告が生成されないようにします。引数の型が間違っていることから、int16はかなり奇妙に見えますが、CallingConventionによって引き起こされる可能性が最も高い問題です。 StdCallを試してみてください。

2番目の引数を「オブジェクト」として宣言すると、デフォルトのマーシャリングはVARIANTになります。 "ref"キーワードで宣言し、LPVARIANTを取得します。

関連する問題