0

パラメータの文字列値を設定するために必要なネイティブ dll があります。以下は、C++ メソッドのシグネチャです。

  __declspec(dllexport) void __stdcall getDetails(_Out_ LPTSTR lpDetails, _In_ UINT uSize)

c++ メソッド

リターン lpDetails=L"test"; のためにこれをハードコーディングしました。

私の c# 署名

   [return: MarshalAs(UnmanagedType.I1)]
   [DllImport("test.dll",CharSet=CharSet.Auto)]
   static extern bool getDetails(StringBuilder result, System.UInt32 uSize);

c# コード

        StringBuilder b = new StringBuilder(1000);
        getDetails(b, 255);
        m = b.ToString(); //always ""
        Console.WriteLine(m);

コードをステップ実行すると、値 (lpDetails) が正しい値に設定されていることがわかります。問題は c# にあり、私が今まで目にしたのは空の文字列だけです。

他の投稿から見つけたものを試しましたが、今のところうまくいきません。

4

1 に答える 1

1

ここにはいくつかの間違いがあります:

  • ネイティブ メソッドは、C++ シグネチャではなく、C シグネチャで示されています (ここではつまらないことをしています :)
  • 関数が事前に割り当てられた場所に詳細を書き込むようにする場合、lPDetails パラメータは OUT ではなく IN です (割り当てられたバッファの長さを示す必要がある 2 番目の引数から見えるように)。
  • あなたの実装lpDetails=L"test"は壊れています。事前に割り当てられたバッファーを関数に提供する場合 (署名が示すように) _tcscpy、詳細を lpDetails に入れる必要があります。関数内に文字列を割り当てたい場合 (実装が示すように、lpDetails を として宣言する必要がありますがLPTSTR*、呼び出し元がそれを解放する方法を知らない可能性があるため、これは悪い設計です (この場合、実際には「テスト」としてはできません)ヒープではなく、データ セグメント内の静的メモリを指します。

これは、Interop がなくても機能しません。

LPTSTR pCallerData; // a pointer variable
void getDetails(LPTSTR lpData, /*what do you use second param for? */)
{
  // lpData is a COPY of pCallerData, not a pointer to it, 
  // so you are not modifying pCallerData, but a local variable
  lpData = "test";
  // after the function exits pCallerData still has the same value as before
}_

より良い実装は次のとおりです。

LPTSTR txt[256]; 
getDetails(txt, 256);
// ----
void getDetails(LPTSTR lpData, int size)
{
_tcscpy(lpDetails, _T("Test")); 
// or more realistically _tcsncpy and properly check 
// if details string is longer than size argument
}_
于 2012-09-12T07:49:17.827 に答える