1

現在、管理されていない C DLL を使用してインターフェイスする USB カメラのラッパーを作成しようとしています。付属のソフトウェアは Qt を使用して C++ で記述されており、このカメラを既に記述した C# アプリケーションに統合しようとしています (アプリケーションは、C# インターフェイスで提供される別のカメラを既に使用しています)。管理されていない/管理されているインターフェイスについてたくさん読んだことがありますが、まだこの特定の DLL に行き詰まっています。

P/DLL の呼び出しに問題があります。私はマネージ/アンマネージ コードを処理する方法についてたくさん読んだことがありますが、関数/パラメーターしか持っていない (他に何もない) ため、C++/CLI ラッパーを作成できず、強制的に作成する必要があるようです。 P/Invoke に固執します。これが正しくない場合は、より効率的であれば、別の方法で助けていただければ幸いです。

とにかく、私は現在、関数の一部 (読み取り: すべて) を呼び出すのに問題があります。例として、この関数を選択してみましょう (Qt のアンマネージ C++ でこのインターフェイスを使用するときに使用されるヘッダー ファイル dijSDK.h から取得):

/** \brief Find cameras currently connected to the host
  *
  * \param[out]      pGuidList   List of unique identifiers of connected cameras; memory is allocated by user
  * \param[in,out]   pNumGuids   Pointer to the number of elements in pGuidList to limit the search
  * \n                           Pointer to the number of cameras found
  * \param[in]       mask        optional mask to limit the results in pGuidList
  *
  * \note
  * -    the function lists all supported cameras that are connected to the host having a driver installed
  * -    the cameras are identified by a string in a defined style:
  * \n  <i>[Name of the camera library resp. camera class]:[camera name]:[Serial number of the camera]</i>
  * -    the optional parameter mask may be used to limit the results returned in pGuidList; 
  * \n   mask is in the same style as the results in pGuidList 
  *      therefore the results can be limited to certain camera classes, camera types,
  *      and cameras with a given serial number */

DIJSDK_EXPORT error_t DijSDK_FindCameras(DijSDK_CamGuid* pGuidList, unsigned int* pNumGuids, const DijSDK_CamGuid mask = NULL);

DIJSDK_EXPORT は次のように定義されています。

#ifndef DIJSDK_EXPORT
 #define DIJSDK_EXPORT externC DLLEXPORT
#endif

そして、上記の関数で使用される 2 つの typedef:

/// Return value of all DijSDK functions
/// \note All return values of type error_t can be casted to the enum <b>DijSDK_EErrorCodeList</b>, see header errorlistinstall.h
typedef int error_t;

// unique DijSDK types
/// Globally unique identifier for all supported cameras. It is used to establish a relation between <b>physical</b> and <b>logical</b> cameras.
typedef char   DijSDK_CamGuid[64];

したがって、関数を見ると、ユーザーは割り当てられた文字列配列とその配列に割り当てられた文字列の数を渡し、関数は一連の文字列とそれが返す文字列の数を返す必要があります。これをC#で実装する方法がまったくわかりません。DllImportpGuidList を次のように渡すなど、関数のさまざまな宣言を試みました...

  • StringBuilder

渡した変数が初期化されvar = new StringBuilder(64)、渡された変数uintは 1 でした。

  • StringBuilder[]

私が渡した変数がで初期化された場所は、関数に渡されたvar = new StringBuilder[length]場所lengthでしたuint

  • IntPtr 渡した変数が で初期化されたMarshal.AllocCoTaskMem(64 * length * Marshal.SystemDefaultCharSize)場所、lengthは上記と同じ uint です

そして、pNumGuidsとして渡されましたref uint。引数 formaskは省略可能であり、使用する必要がないため、これを渡しません。

PInvokeStackImbalanceマネージ インポートとアンマネージ DLL の署名が一致しないため、常にエラーが発生しますが、正しい署名が何であるかがわかりません。

扱っているすべての関数について質問がありますが、一度に 1 つずつ処理します。最初に使用する関数は、コールバックの関数ポインタ引数と void ポインタ引数を受け取る「init」関数であり、関連データですが、コールバックを使用する必要がない場合は、引数なしで呼び出すことができます。それは P/Invoking です。この質問の関数は、接続されているデバイスのリストを取得するために呼び出す必要がある関数です。これを機能させることができれば、残りのほとんどの機能を理解できると思います。

私が扱っている SDK とドキュメントは、それを提供している会社からオンラインで公開されていません。すべてのコード/ドキュメントを表示したい場合は、ファイルサーバーに投稿してリンクを投稿できます。

どんな助けでも大歓迎です!やり残したことがある場合は、必ずやじてください = P

解決策: ヘルプの後、私はそれを機能させることができました:

DllImport:

[DllImport(DLL,CallingConvention=CallingConvention.Cdecl)]
        public static extern error_t DijSDK_FindCameras([Out] DijSDK_CamGuid[] pCamGuid, ref uint pNumGuids, string mask);

DijSDK_CamGuid に使用する構造体:

[StructLayout(LayoutKind.Sequential,Size=64)]
public struct DijSDK_CamGuid
{
    [MarshalAs(UnmanagedType.ByValArray,SizeConst=64)]
    public char[] id;
}

そしてfindCameras()機能:

private void findCameras()
{
     uint cameralistlen = 5;
     DijSDK_CamGuid[] cameralist = new DijSDK_CamGuid[cameralistlen];
     result = Jenoptik.DijSDK_FindCameras(cameralist, ref cameralistlen, null);
}
4

2 に答える 2

1

マネージ コードで ID を文字列として処理する必要がありますか? そうでない場合は、おそらく次のようなものが機能し、バイトを不透明なバイト配列として扱います。

[StructLayout(LayoutKind.Sequential)]
public struct DijSDK_CamGuid
{
  [MarshalAs(UnmanagedType.ByValAray,SizeConst=64)]
  public byte[] id;
}

次に、タイプのパラメーターを取るために使用する p/invoke 署名を宣言します。

DijSDK_CamGuid* 
于 2013-01-09T18:08:43.120 に答える
1

このように宣言してみてください:

    [DllImport("whatever.dll", CallingConvention = CallingConvention.Cdecl)]
    extern public static int DijSDK_FindCameras(byte[] pGuidList, ref int pNumGuids, byte[] mask);

そしてそれを次のように使用します:

    byte[] CamGuids = new byte[64 * 32];    // Up to 32 cameras
    int GuidsCount = CamGuids.Length / 64;
    int result = DijSDK_FindCameras(CamGuids, ref GuidsCount, null);
于 2013-01-09T19:13:28.263 に答える