1

我目前正在尝试为使用非托管 C DLL 进行接口的 USB 相机编写包装器。提供的软件是使用 Qt 用 C++ 编写的,我正在尝试将此相机集成到我已经编写的 C# 应用程序中(该应用程序已经使用了一个带有 C# 接口的不同相机)。我读过一堆关于非托管/托管接口的文章,但我仍然被这个特定的 DLL 所困扰。

我在处理 P/Invoking DLL 时遇到了麻烦。我已经阅读了大量关于处理托管/非托管代码的方法,似乎因为我只有函数/参数(没有别的),我无法编写 C++/CLI 包装器并被迫坚持 P/Invoke。如果这是不正确的,如果更有效的话,将不胜感激对替代方法的一些帮助。

无论如何,我目前无法调用一些(阅读:全部)函数。例如,让我们选择这个函数(取自 dijSDK.h,在 Qt 的非托管 C++ 中使用此接口时要使用的头文件):

/** \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

以及上述函数中使用的两个 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]哪里传递给函数。lengthuint

  • IntPtr 我传入的变量是用 初始化的Marshal.AllocCoTaskMem(64 * length * Marshal.SystemDefaultCharSize),哪里length是和上面一样的 uint

然后pNumGuids作为ref uint. 我不提交参数,mask因为它是可选的,我不需要使用它。

由于托管导入的签名和非托管 DLL 的签名不匹配,我经常得到一个PInvokeStackImbalance,但我无法弄清楚正确的签名是什么。

我对我正在处理的所有功能都有疑问,但我会一次处理一个。我使用的第一个函数是一个“init”函数,它接受一个函数指针参数和一个用于回调的 void 指针参数及其关联数据,但如果我不需要使用回调,我可以不带参数调用它那就是 P/Invoking 就好了。这个问题中的函数是我需要调用的函数以获取附加设备的列表。我想如果我能让这个工作正常,我就能弄清楚其余的大部分功能。

我正在使用的 SDK 和文档并未从提供它的公司在线公开获得。如果有人希望它查看所有代码/文档,我可以将其发布在文件服务器上并发布指向它的链接。

任何帮助将非常感激!如果有什么我遗漏的,请务必质问我=P

解决方案: 在帮助之后,我设法让它工作:

DLL导入:

[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 回答