提问人:Tony 提问时间:11/2/2012 最后编辑:RobᵩTony 更新时间:7/1/2021 访问量:5287
将 C++/CLI 类方法作为 C 函数指针传递
Passing C++/CLI Class Method as C function pointer
问:
我有一个提供此标头的第三方 C 库:
//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 来完成。由于删除构造函数包含“this”并且不需要静态方法,因此我不需要将“this”传递到 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# 测试器,所有这些都可以很好地编译和运行:
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
悬而未决的问题:
- 我有一种感觉,我需要使用 gcroot 和/或 pin_ptr?如果 那么,如何?哪里?
谢谢。
答:
-1赞
whats_wrong_here
8/1/2019
#1
GCReate 应该位于 ref 类存储委托的位置,例如:
gcroot<CLibraryDelegate^> managedDelegate;
评论
0赞
Ben Voigt
7/1/2021
它不仅不应该,而且不能。 是非托管类型,不能是 的成员。gcroot
ref class
评论
gcroot