在C#中封送字符串、指针(使用P/Invoke在C#中为C DLL编写包装器)

在C#中封送字符串、指针(使用P/Invoke在C#中为C DLL编写包装器),c#,arrays,string,pinvoke,marshalling,C#,Arrays,String,Pinvoke,Marshalling,我目前正在尝试为USB摄像头编写一个包装器,它使用一个非托管的C DLL接口。所提供的软件是用QT用C++编写的,我正在尝试把这个相机集成到我已经编写的C语言应用程序中(应用程序已经使用了一个带有C接口的不同的摄像机)。我已经读了很多关于非托管/托管接口的书,但是我仍然被这个特定的DLL卡住了 我在处理p/调用DLL时遇到问题。我已经读了很多关于处理托管/非托管代码的方法的书,似乎因为我只有函数/参数(而没有其他),所以我无法编写C++/CLI包装,不得不坚持使用P/Invoke。如果这是不真实

我目前正在尝试为USB摄像头编写一个包装器,它使用一个非托管的C DLL接口。所提供的软件是用QT用C++编写的,我正在尝试把这个相机集成到我已经编写的C语言应用程序中(应用程序已经使用了一个带有C接口的不同的摄像机)。我已经读了很多关于非托管/托管接口的书,但是我仍然被这个特定的DLL卡住了

我在处理p/调用DLL时遇到问题。我已经读了很多关于处理托管/非托管代码的方法的书,似乎因为我只有函数/参数(而没有其他),所以我无法编写C++/CLI包装,不得不坚持使用P/Invoke。如果这是不真实的,如果更有效的话,我们将感谢您提供其他方法的帮助

无论如何,我现在调用一些(读:all)函数有困难。举个例子,让我们选择这个函数(取自dijSDk.h,在Qt中使用非托管C++中使用此接口时使用的头文件):

以及上述函数中使用的两个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];
private void findCameras()
{
     uint cameralistlen = 5;
     DijSDK_CamGuid[] cameralist = new DijSDK_CamGuid[cameralistlen];
     result = Jenoptik.DijSDK_FindCameras(cameralist, ref cameralistlen, null);
}
用于DijSDK_CamGuid的结构:

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

/// 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];
private void findCameras()
{
     uint cameralistlen = 5;
     DijSDK_CamGuid[] cameralist = new DijSDK_CamGuid[cameralistlen];
     result = Jenoptik.DijSDK_FindCameras(cameralist, ref cameralistlen, null);
}

是否需要将托管代码中的id作为字符串处理?如果不是,也许类似的方法可以工作,将字节视为不透明的字节数组:

[StructLayout(LayoutKind.Sequential)]
public struct DijSDK_CamGuid
{
  [MarshalAs(UnmanagedType.ByValAray,SizeConst=64)]
  public byte[] id;
}
然后声明要使用的p/invoke签名,并获取以下类型的参数:

DijSDK_CamGuid* 

尝试这样声明:

    [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);

只要我把数据输入到托管代码中,我想我就能管理。我希望它是一个字符串,但我可以将字符/字节数组转换为字符串,所以这可能会起作用。我要试一试。谢谢因此,这不起作用,因为我无法获取结构的指针(托管类型的指针)。我确实记得读过关于传递结构数组的文章,所以我将对此进行研究。是的,可能有一些MarshalAs mumbjo jumbo也可以处理字符串,这种方法是我能想到的最快的方法。您可能也会从这里得到一些启发:我尝试只传入一个DijSDK_CamGuid(而不是数组或指向数组的指针),还传入一个值为“1”的uint,但仍然得到一个不平衡的堆栈。我迷路了真的吗?DijSDK_FindCameras看起来像是返回了一个DijSDK_Camguid列表,而不是一个。我在声明中添加了[Out],但我认为“呼叫会议”做到了!现在命令运行了,但是字节数组被初始化为0(计数也是0)。它可能正在工作,但我需要确保摄像头正常通信。摄像头在提供的软件中工作正常,该函数只是将其两个输入修改为零/零。
    byte[] CamGuids = new byte[64 * 32];    // Up to 32 cameras
    int GuidsCount = CamGuids.Length / 64;
    int result = DijSDK_FindCameras(CamGuids, ref GuidsCount, null);