gpt4 book ai didi

c# - 从 C++ 回调到 C#

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:16:04 26 4
gpt4 key购买 nike

假设我有一个用于计算 PI 的 C++ 库函数:

// pi.h:
#ifdef BUILDING_DLL
#define DLL_MACRO __declspec(dllexport)
#else
#define DLL_MACRO __declspec(dllimport)
#endif

namespace Cpp {
class PI {
public:
static double DLL_MACRO compute();
};
};

// pi.cpp:
#include "pi.h"
#include <cmath>

double
Cpp::PI::compute() {
// Leibnitz summation formulae:
double sum = 0.0;
for(long n = 0; n < 100*1000*1000; n++)
sum += 4.0*pow(-1.0, n)/(2*n + 1.0);
return sum;
}

我需要从 C# 调用这个函数,我想使用 C++/CLI 作为“桥梁”。然而,这个 C++ 函数有点慢。因此,调用此函数的 C# 代码需要获取回调,以 % 的形式告诉它该函数已经走了多远。C# 代码可能需要一些状态,例如一个进度条,用来处理这些信息。因此,来自 C++ 的回调必须进入 C# 端的成员函数。

所以我介绍一下:

// piCLI.h: The C++/CLI "bridge" between C# and C++
#include "pi.h"
#pragma once
namespace CLI {
public ref class PI abstract {
public:
double compute() {
return Cpp::PI::compute();
}
virtual void progress(int percentCompleted) = 0;
};
};

 namespace CSharp
{
public class PI : CLI.PI
{
public override void progress(int percentCompleted)
{
System.Console.WriteLine(percentCompleted + "% completed.");
}
}
}

现在调用 CSharp.PI.compute() 工作正常:-)。它按预期将调用转发给 Cpp::PI::compute()。

但是我如何让 C++ 库在 Cpp::PI::compute() 运行时将进度更新转发到 CSharp.PI.progress()?

提前感谢您的回答!

最佳答案

我也会采用函数指针/委托(delegate)方法:

// pi.h:
#pragma once

#ifndef DLL_MACRO
#ifdef BUILDING_DLL
#define DLL_MACRO __declspec(dllexport)
#else
#define DLL_MACRO __declspec(dllimport)
#endif
#endif

namespace Cpp {
typedef void (__stdcall *ComputeProgressCallback)(int);

class PI {
public:
static double DLL_MACRO compute(ComputeProgressCallback callback);
};
}

// pi.cpp:
#include "pi.h"
#include <cmath>

double Cpp::PI::compute(Cpp::ComputeProgressCallback callback) {
double sum = 0.;
for (long n = 0L; n != 100000000L; ++n) {
sum += 4. * std::pow(-1., n) / (2L * n + 1.);
callback(/*impl*/);
}
return sum;
}
// piCLI.h: The C++/CLI "bridge" between C# and C++
#pragma once
#include "pi.h"

namespace CLI {
public delegate void ComputeProgressDelegate(int percentCompleted);

public ref class PI abstract sealed {
public:
static double compute(ComputeProgressDelegate^ callback) {
using System::IntPtr;
using System::Runtime::InteropServices::Marshal;

IntPtr cbPtr = Marshal::GetFunctionPointerForDelegate(callback);
return Cpp::PI::compute(
static_cast<Cpp::ComputeProgressCallback>(cbPtr.ToPointer())
);
}
};
}
namespace CSharp {
public static class PI {
public static double compute() {
CLI.PI.compute(
percentCompleted => System.Console.WriteLine(
percentCompleted.ToString() + "% completed."
)
);
}
}
}

或者,覆盖抽象的 progress 方法而不是在 C# 端创建委托(delegate):

// piCLI.h: The C++/CLI "bridge" between C# and C++
#pragma once
#include "pi.h"

namespace CLI {
public ref class PI abstract {
delegate void ComputeProgressDelegate(int percentCompleted);

public:
double compute() {
using System::IntPtr;
using System::Runtime::InteropServices::Marshal;

ComputeProgressDelegate^ callback = gcnew ComputeProgressDelegate(
this,
&PI::progress
);
IntPtr cbPtr = Marshal::GetFunctionPointerForDelegate(callback);
return Cpp::PI::compute(
static_cast<Cpp::ComputeProgressCallback>(cbPtr.ToPointer())
);
}

protected:
virtual void progress(int percentCompleted) abstract;
};
}
namespace CSharp {
public sealed class PI : CLI.PI {
protected override void progress(int percentCompleted) {
System.Console.WriteLine(
percentCompleted.ToString() + "% completed."
);
}
}
}

关于c# - 从 C++ 回调到 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6507705/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com