将C ++ / CLI类方法传递为C函数指针 [英] Passing C++/CLI Class Method as C function pointer

查看:132
本文介绍了将C ++ / CLI类方法传递为C函数指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个提供此标头的第三方C库:

I have a third-party C library that provides this header:

//CLibrary.h
#include <Windows.h>
#include <process.h>
typedef void (WINAPI *CLibEventCallback)(int event, void *data);
__declspec(dllexport) bool CLibStart (CLibEventCallback callback, void *data);

// CLibrary.c -- sample implementation
static CLibEventCallback cb;

void _cdecl DoWork (void *ptr)
{
    for (int i = 0; i < 10; ++i)
    {
        cb (i*i, ptr);
        Sleep (500);
    }
}

__declspec(dllexport) bool CLibStart (CLibEventCallback callback, void *data)
{
    cb = callback; // save address for DoWork thread...
    _beginthread (DoWork, 0, data);
    return true;
}

我需要创建一个可以调用 CLibStart的C ++ / CLI类并提供一个类方法作为函数指针。如下所示,这需要使用GetFunctionPointerForDelegate完成。因为delete构造函数包含'this'并且不需要静态方法,所以我不需要将'this'传递给CLibStart。

I need to create a C++/CLI class that can call CLibStart and provide a class method as the function pointer. As suggested below, this needs to be done with GetFunctionPointerForDelegate. Because the delete constructor includes 'this' and doesn't require a static method, I don't need to pass 'this' into CLibStart.

using namespace System;
using namespace System::Runtime::InteropServices;

namespace Sample {
    public ref class ManagedClass
    {   
        delegate void CLibraryDelegate (int event, void *data);

    private:
        CLibraryDelegate^ managedDelegate;
        IntPtr unmanagedDelegatePtr;
        int someInstanceData;

    public:
        ManagedClass() 
        { 
            this->managedDelegate = gcnew CLibraryDelegate(this, &ManagedClass::ManagedCallback);
            this->unmanagedDelegatePtr = Marshal::GetFunctionPointerForDelegate(this->managedDelegate);
            this->someInstanceData = 42;
        }

        void Start ()
        {
            // since the delegate includes an implicit 'this' (as static function is not needed)
            // I no longer need to pass 'this' in the second parameter!
            CLibStart ((CLibEventCallback) (void *) unmanagedDelegatePtr, nullptr); 
        }

    private:
        void Log (String^ msg)
        {
            Console::WriteLine (String::Format ("someInstanceData: {0}, message: {1}", this->someInstanceData, msg));  
        }

        void ManagedCallback (int eventType, void *data)
        {
            // no longer need "data" to contain 'this'
            this->Log (String::Format ("Received Event {0}", eventType));
        }
    };
}

使用C#测试器,所有这些编译和运行都很好:

All of this compiles and runs fine using this C# tester:

using System;
using Sample;

namespace Tester
{
    class Program
    {
        static void Main(string[] args)
        {
            var mc = new ManagedClass();
            mc.Start();
            Console.ReadKey();
        }
    }
}

样本输出:

Received Event 0
Received Event 1
Received Event 4
Received Event 9
Received Event 16
Received Event 25
Received Event 36
Received Event 49
Received Event 64
Received Event 81

悬而未决的问题:


  1. 我有我需要使用gcroot和/或pin_ptr的感觉吗?如果
    是这样,怎么办?

谢谢。

推荐答案

这个问题很老,但是也许对某人有用:

The question is old, but maybe for someone will be useful:

gcroot应该放在引用类存储委托的位置,例如:

gcroot should be in place where ref class stores delegate, like:

gcroot<CLibraryDelegate^> managedDelegate;

这篇关于将C ++ / CLI类方法传递为C函数指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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