传递给外部函数的in ref结构体异常:pid被识别为0而非实际值
问题分析与解决方案
问题描述
调用get_argv_of_pid函数时,C侧读取到的GetArgvOptions结构体中pid字段始终为0,但C#代码中已确认调用前该字段已正确赋值为实际进程ID。
相关代码对比
C头文件定义
struct GetArgvOptions { uint skip; pid_t pid; bool nuls; }; bool get_argv_of_pid(const struct GetArgvOptions* options, struct ArgvResult* result);
C#结构体与DllImport定义
[StructLayout(LayoutKind.Sequential)] struct GetArgvOptions { public nuint skip; public nint pid; public bool nuls; } [DllImport("libgetargv.dylib", CallingConvention = CallingConvention.Cdecl, SetLastError = true)] static extern bool get_argv_of_pid(in GetArgvOptions options, out ArgvResult result);
C#测试代码
int pid = Environment.ProcessId; GetArgvOptions opt; opt.pid = pid; opt.skip = 0; opt.nuls = false; Console.WriteLine($"pid: {opt.pid}"); ArgvResult res = new ArgvResult(); bool success = get_argv_of_pid(in opt, out res);
根本原因
macOS平台下,C语言的pid_t是32位整数(typedef int pid_t),但C#代码中使用了nint类型——64位系统下nint为8字节,32位系统下为4字节,这直接导致结构体内存布局错位:
- C结构体内存顺序:
skip(4字节)→pid(4字节)→nuls(1字节) - C#结构体内存顺序(64位系统):
skip(8字节)→pid(8字节)→nuls(1字节)
内存大小不匹配会让C函数读取pid时指向错误的内存地址,最终得到无效值0。
修复方案
将C#结构体中的pid字段类型改为int,与C侧的pid_t类型完全对齐:
[StructLayout(LayoutKind.Sequential)] struct GetArgvOptions { public nuint skip; // 与C的uint类型匹配(平台自适应字节长度) public int pid; // 与C的pid_t(int)类型匹配 public bool nuls; }
同时需确保ArgvResult结构体的定义也与C侧完全一致,避免后续出现同类内存布局问题。
内容的提问来源于stack exchange,提问作者Camden Narzt
相关产品推荐
相关产品推荐

