0

0

C# UnmanagedCallersOnly属性方法 C#如何从本地代码回调托管方法

月夜之吻

月夜之吻

发布时间:2026-02-04 09:27:10

|

209人浏览过

|

来源于php中文网

原创

UnmanagedCallersOnly方法不能被本地代码直接回调,它仅使静态方法具备C ABI兼容性且禁用部分JIT优化,但不提供回调机制;真正可行的回调路径是使用委托+Marshal.GetFunctionPointerForDelegate,并需显式指定调用约定、保持委托强引用。

c# unmanagedcallersonly属性方法 c#如何从本地代码回调托管方法

UnmanagedCallersOnly 方法不能被本地代码直接回调

这是最常被误解的一点:UnmanagedCallersOnly 属性只控制「托管方法能否被非托管代码调用」,但它**不提供回调机制**。它只是让一个 static 方法具备 C ABI 兼容签名(如 __cdecl),并禁用 JIT 编译器的某些优化(比如探针、GC 检查),从而能被 GetProcAddress 或函数指针安全调用。但它本身不注册、不导出、不维护任何跨语言回调通道。

本地代码回调托管方法必须靠委托 + Marshal.GetFunctionPointerForDelegate

真正可行的路径是:在托管侧定义一个匹配本地函数签名的委托类型,实例化委托,再用 Marshal.GetFunctionPointerForDelegate 转成原生函数指针,把该指针传给本地库(比如通过初始化 API 或回调注册函数)。关键点:

  • 委托类型必须用 UnmanagedFunctionPointer 显式指定调用约定(通常是 CallingConvention.CdeclStdCall),否则指针调用时会栈失衡
  • 委托实例必须长期存活(不能被 GC 回收),需保存强引用(如 static 字段或 GCHandle.Alloc
  • 若回调可能从非主线程进入,方法体内需注意线程上下文(如 UI 线程需调度,但 UnmanagedCallersOnly 方法默认无上下文)
  • GetFunctionPointerForDelegate 返回的指针在 .NET 5+ 中是稳定的,但仅限于 delegate 实例生命周期内有效

为什么不用 UnmanagedCallersOnly 做回调入口?

因为 UnmanagedCallersOnly 方法没有托管对象实例上下文,无法捕获闭包、无法访问 this、无法调用非静态成员——它本质上就是个裸函数。而绝大多数回调场景需要携带状态(比如传入的 void* 用户数据、事件处理器对象等)。常见错误现象:

雀塔AI
雀塔AI

一站式工作流开发服务平台,从开发配置到推广分成,从AI创意到落地变现全搞定。

下载
  • 试图把 UnmanagedCallersOnly 方法地址硬编码传给本地库,结果调用时崩溃(AccessViolationException 或静默失败)
  • typeof(MyClass).GetMethod("Callback").MethodHandle.GetFunctionPointer() 取地址 —— 这返回的是内部 JIT 地址,不可用于跨语言调用
  • 委托未持久引用,GC 后指针悬空,本地代码一回调就触发 AV

一个最小可运行示例(C# → C DLL 回调)

假设本地 DLL 提供:typedef void (*callback_t)(int code, const char* msg);void set_callback(callback_t cb);

// 托管侧
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void LogCallback(int code, IntPtr msg);

static LogCallback _callback = (code, msg) => { var str = Marshal.PtrToStringUTF8(msg); Console.WriteLine($"[{code}] {str}"); };

// 必须保持引用! static IntPtr _callbackPtr;

static void Init() { _callbackPtr = Marshal.GetFunctionPointerForDelegate(_callback); set_callback((callback_t)_callbackPtr); // P/Invoke 导入的 set_callback }

漏掉 _callback 的 static 引用,或没调用 Init(),回调就会失效。这也是最容易被忽略的环节:不是写对了就能用,而是得管住生命周期。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

534

2023.09.20

typedef和define区别
typedef和define区别

typedef和define区别在类型检查、作用范围、可读性、错误处理和内存占用等。本专题为大家提供typedef和define相关的文章、下载、课程内容,供大家免费下载体验。

109

2023.09.26

c语言typedef的用法
c语言typedef的用法

c语言typedef的用法有定义基本类型别名、定义结构体别名、定义指针类型别名、定义枚举类型别名、定义数组类型别名等。本专题为大家提供typedef相关的文章、下载、课程内容,供大家免费下载体验。

100

2023.09.26

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

563

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

547

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

153

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

204

2025.08.29

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

177

2023.11.23

全国统一发票查询平台入口合集
全国统一发票查询平台入口合集

本专题整合了全国统一发票查询入口地址合集,阅读专题下面的文章了解更多详细入口。

34

2026.02.03

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Django 教程
Django 教程

共28课时 | 3.9万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.4万人学习

Sass 教程
Sass 教程

共14课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号