将托管功能指针作为非托管回调传递 [英] Pass Managed Function Pointer As Unmanaged Callback

查看:133
本文介绍了将托管功能指针作为非托管回调传递的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将托管函数指针 void(*)(void *)传递给我的非托管库。我的非托管库使用带有指向CriticalSection保护的数据帧的指针来调用此回调。在托管回调运行时,由于关键部分,其他任何东西都不能修改数据帧。但是,我只是通过输入回调来获得访问冲突和堆损坏。

I am attempting to pass a managed function pointer void (*)(void *) to my unmanaged library. My unmanaged library calls this callback with a pointer to a frame of data protected by a CriticalSection. While the managed callback is running, nothing else can modify the frame of data due to the Critical Section. However, I am getting Access Violations and Heap Corruptions just by entering the callback.

编辑:我忘了提。 StartStreaming()窃取它管理的线程。此外,它创建了一个单独的线程,用于将新数据调度到给定的回调。回调是在这个单独的线程中调用的。

EDIT: I forgot to mention. The StartStreaming() steals the thread it manages. Furthermore, it creates a separate thread for dispatching new data to the given callback. The callback is called in this separate thread.

到目前为止,我已经完成了以下操作:

So far I have done the follow:

//Start Streaming
streaming_thread_ = gcnew Thread(gcnew ThreadStart(&Form1::WorkerThreadFunc));
streaming_thread_->Start();

其中:

extern "C" {
#include "libavcodec\avcodec.h"
#include "libavutil\avutil.h"
}

namespace TEST_OCU {

delegate void myCallbackDelegate(void * usr_data); //Declare a delegate for my unmanaged code

public ref class Form1 : public System::Windows::Forms::Form
{
    public:

    static void WorkerThreadFunc()
    {
        myCallbackDelegate^ del = gcnew myCallbackDelegate(&Form1::frame_callback);

        MessageBox::Show("Starting to Streaming", "Streaming Info");
        if(rtsp_connection_ != NULL)
            rtsp_connection_->StartStreaming();
            //rtsp_connection_->StartStreaming((void (*)(void *)) System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(del).ToPointer() );
        MessageBox::Show("Done Streaming", "Streaming Info");
    }

    static void __cdecl frame_callback(void * frame)
    {
        AVFrame * casted_frame = (AVFrame *)frame;
    }

private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e) 
    {
        if(rtsp_connection_ == NULL)
            rtsp_connection_ = new NeyaSystems::RTSPConnection("rtsp://url");
    }

    private: static RTSPConnection * rtsp_connection_ = NULL;
}
}




  • 我省略了很多毫无意义的代码...

  • StartStreaming 默认为NULL指针,在这种情况下我不会损坏

  • StartStreaming 与委派的函数指针会导致堆损坏

  • RTSPConnection 在本机C ++中实现,并且还包含C调用(libavcodec)

  • RTSPConnection 包含两个线程,即通信和框架调度线程(调用托管回调)

    • I've omitted a lot of pointless code...
    • StartStreaming defaults to a NULL pointer, in this case I get no corruption
    • StartStreaming with the delegated function pointer causes heap corruption
    • RTSPConnection is implemented in native C++ and contains C calls as well (libavcodec)
    • RTSPConnection contains two threads, communication and frame dispatch thread (calls the managed callback)
    • 有人可以给我一个面包屑吗?

      Could anyone give me a breadcrumb? Thank you so much in advance.

      推荐答案

      编辑:跨线程调用不是问题。如果非托管调用者希望调用__cdecl函数,则必须使用UnmanagedFunctionPointerAttribute属性来装饰委托类型。

      not a problem with cross-thread calls. If the unmanaged caller expects to call a __cdecl function, then you have to decorate the delegate type with an UnmanagedFunctionPointerAttribute attribute.

      using namespace System::Runtime::InteropServices;
      
      [UnmanagedFunctionPointerAttribute(CallingConvention::Cdecl)] 
      delegate void myCallbackDelegate(void * usr_data); 
      

      这篇关于将托管功能指针作为非托管回调传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆