所以我有一个C++函数,采用一个方法作为一个std函数采取原始指针并填充它并返回所有值的累积,我希望公开这到一个C#API。这里是我的方法:通过C#委托数组引用非托管代码通过函数指针
// acc_process.h
#include <vector>
#include <numeric>
template<typename T>
static T process_accumulate(std::function<void(T*, size_t)> populate_func)
{
std::vector<T> data(1000);
populate_func(data.data(), data.capacity());
return std::accumulate(data.begin(), data.end(), 0);
}
其次是CLI包装揭露这对C#:
// acc_process_cli.h
#include acc_process.h
#pragma managed(push, off)
typedef void(__stdcall *ReadCallbackDouble)(double* data, size_t data_size);
#pragma managed(pop)
delegate void PopFunctionDoubleDelegate(cli::array<double>^% data, size_t data_size);
public ref class ProcessDoubleCLI {
public:
ProcessDoubleCLI() {};
double accumulate_cli(PopFunctionDoubleDelegate^ delegate_func);
};
与实施:
// acc_process_cli.cpp
#include "acc_process_cli.h"
double ProcessDoubleCLI::accumulate_cli(PopFunctionDoubleDelegate^ delegate_func)
{
IntPtr FunctionPointer =
Marshal::GetFunctionPointerForDelegate(delegate_func);
ReadCallbackDouble func_ptr = static_cast<ReadCallbackDouble>(FunctionPointer.ToPointer());
auto func_bind = std::bind(
(void (*)(double* , size_t))func_ptr, std::placeholders::_1, std::placeholders::_2);
return process_accumulate<double>(func_bind);
}
而且最终的C#示例应用程序提供的委托功能用于填充数据(例如process_accumulate的populate_func参数):
// test.cs
class DoubleReader {
public static void PopulateFunctionDoubleIncr(ref double[] data, ulong size_data) {
ulong idx = 0;
ulong size = size_data;
while (idx < size) {
data[idx] = (double)idx;
++idx;
}
}
static void Main(string[] args)
{
DoubleReader dr = new DoubleReader();
PopFunctionDoubleDelegate func = PopulateFunctionDoubleIncr;
ProcessDoubleCLI process = new ProcessDoubleCLI();
double acc_value = process.accumulate_cli(func);
}
}
但是,当传递给C#上的PopulateFunctionDoubleIncr时,数组始终为空。我是否正确地做这件事或者这是可能的?
注意:如果这是可能的,是否也可以直接从某种托管向量引用转换为非托管std ::向量引用,而不是原始指针,那会更好。
呃,解决std :: bind错误是很少的喜悦。在func_ptr上投的是非常非常邪恶的。函数指针是'__stdcall',但模板需要'__cdecl'函数。你不能那样做。 –
这绝对不是一个喜欢处理std函数和绑定在一般情况下,但我已经遍及SO和微软网站:[链接](https://msdn.microsoft.com/en-us/library/367eeye0( v = vs.140).aspx),我的方法显然是推荐的方法,但我试图委托一个函数,该函数需要一个数组引用,我找不到解决方案。我也尝试了其他调用约定(__clrcall,__cdecl),结果相同。 – mconte
我在VS2015上运行这个,而不是2017,我不确定编译器错误是什么,如果有的话。我只是试图用尽可能少的代码重现这个问题。 – mconte