在非托管代码中处理托管委托
Handling Managed Delegates in Unmanaged code
我知道我可以在技术上做到这一点,但我想实现尽可能干净的解决方案。情况如下:
我有一个托管库,它封装了一个非托管C样式库。我目前正在包装的C样式库功能进行一些涉及字符串列表的处理。库的客户端代码可以提供委托,这样在列表处理过程中,如果遇到"无效"场景,库可以通过该委托回调到客户端,并允许他们选择要使用的策略(抛出异常、替换无效字符等)
理想情况下,我希望所有托管C++都隔离在一个函数中,然后能够调用一个单独的函数,该函数只接受非托管参数,这样所有本机C++和非托管代码都会在这一点上隔离。事实证明,为这个非托管代码提供回调机制是我的症结所在
#pragma managed
public delegate string InvalidStringFilter(int lineNumber, string text);
...
public IList<Result> DoListProcessing(IList<string> listToProcess, InvalidStringFilter filter)
{
// Managed code goes here, translate parameters etc.
}
#pragma unmanaged
// This should be the only function that actually touches the C-library directly
std::vector<NativeResult> ProcessList(std::vector<char*> list, ?? callback);
在这个片段中,我想将所有的C库访问保留在ProcessList中,但在处理过程中,它需要进行回调,并且这个回调是以InvalidStringFilter委托的形式提供的,该委托是从我的托管库的某个客户端传入的。
.NET可以自动将委托转换为指向函数的指针(如果声明正确的话)。有两个注意事项
- 必须构建C函数STDCALL
- 指向函数的指针不算作对对象的引用,因此必须安排保留一个引用,以使底层对象不会被垃圾回收
http://www.codeproject.com/KB/mcpp/FuncPtrDelegate.aspx?display=Print
如果我正确理解了这个问题,您需要在C++/CLI程序集中声明一个非托管回调函数,该函数充当C库和托管委托之间的桥梁。
#pragma managed
public delegate string InvalidStringFilter(int lineNumber, string text);
...
static InvalidStringFilter sFilter;
public IList<Result> DoListProcessing(IList<string> listToProcess, InvalidStringFilter filter)
{
// Managed code goes here, translate parameters etc.
SFilter = filter;
}
#pragma unmanaged
void StringCallback(???)
{
sFilter(????);
}
// This should be the only function that actually touches the C-library directly
std::vector<NativeResult> ProcessList(std::vector<char*> list, StringCallback);
正如所写的,这段代码显然不是线程安全的。如果您需要线程安全性,则需要其他一些机制来在回调中查找正确的托管委托,可以是ThreadStatic,也可以是回调传递了用户提供的可以使用的变量。
你想做这样的事情:
typedef void (__stdcall *w_InvalidStringFilter) (int lineNumber, string message);
GCHandle handle = GCHandle::Alloc(InvalidStringFilter);
w_InvalidStringFilter callback =
static_cast<w_InvalidStringFilter>(
Marshal::GetFunctionPointerForDelegate(InvalidStringFilter).ToPointer()
);
std::vector<NativeResult> res = ProcessList(list, callback);
相关文章:
- 如何在 c++ 非托管代码中反序列化 byte[] 的 json 字符串?
- 如何使用指针直接从托管代码中的非托管代码中读取矢量数据
- 异步接口托管 - > 非托管代码
- 从C++(非托管代码)检索数组到 C 尖锐形式(托管)
- 将C++非托管代码转换为 C#
- 将托管事件处理程序传递给 Linux 中的非托管代码
- 使用 P/Invoke 时存储非托管代码的数据
- Windows 服务导入C++非托管代码
- P/从获取"tried to access protected memory error"调用非托管C++代码
- 将数据从非托管代码传递到托管代码
- 从 VB.NET 调用非托管代码C++ dll
- 当C#中的字节数组传递给结构中的非托管代码时,会发生什么情况
- 在托管代码和非托管代码之间传递非托管结构的安全数组
- 如何调试C++非托管代码中的较低级别文件访问异常/崩溃
- 自定义Direct2D呈现托管代码和非托管代码之间的批封送处理
- winform中的C++非托管代码
- 如何减少 Visual Studio 非托管代码中的发布生成时间
- 如何处理非托管代码中的托管异常
- 在托管代码中使用非托管代码时处理错误(c++, C, c++ /CLI, c#)
- 在非托管代码中处理托管委托