現在、管理されていない 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#で実装する方法がまったくわかりません。DllImport
pGuidList を次のように渡すなど、関数のさまざまな宣言を試みました...
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);
}