C#向原生函数传递null委托的处理机制及结果问询
问题背景
假设有一个名为mylib.so的C语言库,暴露以下接口:
typedef void (*EventCallback)(int); // Windows平台下会额外定义对应的declspec宏 void AddEventHandler(EventCallback ec);
在C#中,我们按如下方式调用mylib.so:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate void EventCallback(int type); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate void AddEventHandlerFn(EventCallback? ec); // 在后续代码中... IntPtr libHandle = NativeLibrary.Load("mylib.so"); var addEventHandler = Marshal.GetDelegateForFunctionPointer<AddEventHandlerFn>( NativeLibrary.GetExport(libHandle, "AddEventHandler") ); addEventHandler(null);
问题:当在C#中调用addEventHandler(null)时,C语言函数中是否会接收到(EventCallback)0?若否,实际会发生什么?
答案
是的,C语言函数会接收到(EventCallback)0(即空函数指针)。
具体原因:
- 在C#与非托管代码的封送逻辑中,当传递
null作为委托类型参数时,CLR会直接将其转换为对应非托管环境的空指针。 - 这里的
EventCallback?是可空委托类型,传递null时,封送器会严格按照约定将其映射为C语言里的空函数指针(EventCallback)0。 - 只要调用约定(此处为
Cdecl)与非托管库的约定匹配,这种空值封送是完全符合预期的,不会产生额外异常——除非C库本身对空指针有非法操作,但这属于库自身的逻辑问题,和封送机制无关。
内容的提问来源于stack exchange,提问作者itzjackyscode
相关产品推荐
相关产品推荐

