简体   繁体   English

C++ 到 C#:PInvoke \\ 编组具有复杂类型的回调

[英]C++ to C#: PInvoke \ Marshaling a callback with a complex type

I'm working with a C++ SDK to connect my C# code to some CCTV cameras.我正在使用 C++ SDK 将我的 C# 代码连接到一些闭路电视摄像机。 I want to use a method of the SDK to set a callback from which I can retrieve frame information.我想使用 SDK 的一个方法来设置一个回调,我可以从中检索帧信息。

The code from the .h file: .h 文件中的代码:

typedef struct _frame_info
{
    unsigned long       deviceID;
    unsigned long       channel;
    unsigned long       frameType;
    unsigned long       length;
    unsigned long       keyFrame;
    unsigned long       width;
    unsigned long       height;
    unsigned long       frameIndex;
    unsigned long       frameAttrib;
    unsigned long       streamID;
    long long           time;
    long long           relativeTime;
} FRAME_INFO;

typedef void (__stdcall *PLAY_DATA_CALLBACK)(long lPlayHandle,
    FRAME_INFO frameInfo, unsigned char *pBuffer, void *pUser);

extern "C" __declspec(dllimport) BOOL __stdcall SetPlayDataCallBack(
    long lPlayHandle, PLAY_DATA_CALLBACK fPlayDataCallBack, void *pUser);

The PInvoke code: PInvoke 代码:

[StructLayout(LayoutKind.Sequential, Pack = 0)]
public class FrameInfo
{
    public uint deviceID;
    public uint channel;
    public uint frameType;
    public uint length;
    public uint keyFrame;
    public uint width;
    public uint height;
    public uint frameIndex;
    public uint frameAttrib;
    public uint streamID;
    public long time;
    public long relativeTime;
}

public delegate void PlayDataCallback(int playbackHandle,
    FrameInfo frameInfo, IntPtr buffer, IntPtr userData);

[DllImport("SDK.dll")]
public static extern bool SetPlayDataCallBack(int playbackHandle,
    PlayDataCallback playDataCallback, IntPtr userData);

The code using the PInvoke code:使用 PInvoke 代码的代码:

// Class member to keep the callback alive
PlayDataCallback _callbackDelegate;

// Assigning the callback
_callbackDelegate = new PlayDataCallback(MyCallback);

// Setting the callback
SetPlayDataCallBack(_playbackId, _callbackDelegate, IntPtr.Zero);

// The callback
private void MyCallback(int playbackHandle, FrameInfo frameInfo,
    IntPtr buffer, IntPtr userdata)
{
    // wishful thinking
}

When I run the code I get the error: "System.NullReferenceException was unhandled Message: Object reference not set to an instance of an object."当我运行代码时,出现错误:“System.NullReferenceException 未处理消息:未将对象引用设置为对象的实例。”

I tried Changing the callback signature to the following (ie instead of FrameInfo using IntPtr) -我尝试将回调签名更改为以下内容(即使用 IntPtr 代替 FrameInfo) -

public delegate void PlayDataCallback(int playbackHandle, IntPtr frameInfo,
    IntPtr buffer, IntPtr userData);

Result - the callback was actually called (!) but there was nothing I could do with IntPtr frameInfo, eg trying to call from the callback:结果 -实际上调用了回调(!),但是我无法使用 IntPtr frameInfo 做任何事情,例如尝试从回调中调用:

Marshal.PtrToStructure(frameInfo, typeof(FrameInfo));

or或者

var a = new IntPtr[14];
Marshal.Copy(frameInfo, a, 0, 1); // '1' is just an example, any number except '0' results in the same error

Resulted in the error: "System.AccessViolationException was unhandled Message: Attempted to read or write protected memory. This is often an indication that other memory is corrupt."导致错误:“System.AccessViolationException was unhandled Message: Attempted to read or write protected memory。这通常表明其他内存已损坏。”

I also tried using the UnmanagedFunctionPointer attribute above the callback delegate and got the same error.我还尝试使用回调委托上方的UnmanagedFunctionPointer属性并得到相同的错误。

As you may see I am taking my first steps of juggling between managed and unmanaged code.正如您所看到的,我正在开始在托管代码和非托管代码之间进行切换。 I read a bunch of articles and listened to a couple of pluralsight topics that seemed relevant but none talked about the issue above.我读了一堆文章,听了几个看似相关的复数主题,但没有人谈到上述问题。 I think that something is wrong with the way I marshaled the FrameInfo struct but I have already marshaled similar structs successfully so honestly I have no idea what to do next.我认为我编组 FrameInfo 结构的方式有问题,但我已经成功地编组了类似的结构,所以老实说我不知道​​下一步该怎么做。

I will appreciate any help.我将不胜感激任何帮助。 Thanks.谢谢。

You translated the struct as a class.您将结构翻译为一个类。 That is a reference type.那是一个引用类型。 Which means that it is passed by reference.这意味着它是通过引用传递的。 However the C++ code passes the strict by value.然而,C++ 代码通过了严格的值。

Fix the problem by declaring FrameInfo as a struct.通过将FrameInfo声明为结构来解决问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM