You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

传递给外部函数的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 16:22:26