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

同一系统中如何通过命名管道将C语言结构体数据传递到C#应用程序

命名管道传输C结构体到C#实现方案

核心要求为两端保持结构体内存布局、字段类型、字节序完全一致,直接传输二进制字节流即可完成传递。

C端实现修改

原有代码基于字节模式的命名管道,只需直接写入结构体的二进制内存内容即可:

#include <windows.h>
#include <stdio.h>

HANDLE fileHandle;
// 定义待传输的结构体
struct data
{
    unsigned int count;
    unsigned int total;
};

void ReadString(char* output) {
  ULONG read = 0;
  int index = 0;
  do {
    ReadFile(fileHandle, output + index++, 1, &read, NULL);
  } while (read > 0 && *(output + index - 1) != 0);
}

int main()
{
  // 打开管道
  fileHandle = CreateFileW(TEXT("\\\\.\\pipe\\my-very-cool-pipe-example"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
  if (fileHandle == INVALID_HANDLE_VALUE) {
      printf("打开管道失败");
      return 1;
  }

  // 读取C#端发送的字符串(原有逻辑保留)
  char* buffer = new char[100];
  memset(buffer, 0, 100);
  ReadString(buffer);
  printf("read from pipe server: %s\r\n", buffer);

  // 发送字符串到C#端(原有逻辑保留)
  const char* msg = "hello from C\r\n";
  DWORD written = 0;
  WriteFile(fileHandle, msg, strlen(msg), &written, NULL);

  // 新增:发送结构体数据
  struct data sendData = {123, 4567};
  WriteFile(fileHandle, &sendData, sizeof(struct data), &written, NULL);

  CloseHandle(fileHandle);
  return 0;
}

C#端实现修改

原有代码使用StreamReader/StreamWriter处理文本数据,传输二进制结构体需直接操作管道字节流,同时定义内存布局匹配的C#结构体:

using System;
using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

namespace PipeServerCsharp
{
    // 定义和C端内存布局完全一致的结构体
    [StructLayout(LayoutKind.Sequential)]
    public struct Data
    {
        public uint count; // 对应C端unsigned int
        public uint total;
    }

    class Program
    {
        static void Main(string[] args)
        {
            var instances = new Task[5];
            for (int i = 0; i < instances.Length; i++)
            {
                instances[i] = Task.Run(() =>
                {
                    using var namedPipeServer = new NamedPipeServerStream(
                        "my-very-cool-pipe-example", 
                        PipeDirection.InOut, 5, 
                        PipeTransmissionMode.Byte);
                    namedPipeServer.WaitForConnection();

                    // 发送字符串到C端(原有逻辑调整,直接写字节避免编码问题)
                    byte[] strBuf = System.Text.Encoding.UTF8.GetBytes("Hello from c#\0");
                    namedPipeServer.Write(strBuf, 0, strBuf.Length);
                    namedPipeServer.Flush();
                    namedPipeServer.WaitForPipeDrain();

                    // 读取C端发送的字符串(原有逻辑)
                    byte[] readBuf = new byte[1024];
                    int readLen = namedPipeServer.Read(readBuf, 0, readBuf.Length);
                    string cStr = System.Text.Encoding.UTF8.GetString(readBuf, 0, readLen).TrimEnd('\r', '\n');
                    Console.WriteLine($"read from pipe client: {cStr}");

                    // 新增:读取结构体数据
                    byte[] structBuf = new byte[Marshal.SizeOf<Data>()];
                    readLen = namedPipeServer.Read(structBuf, 0, structBuf.Length);
                    // 字节数组转结构体(非安全代码版本,也可使用Marshal实现)
                    Data receivedData;
                    unsafe
                    {
                        fixed (byte* p = structBuf)
                        {
                            receivedData = *(Data*)p;
                        }
                    }
                    Console.WriteLine($"收到结构体:count={receivedData.count}, total={receivedData.total}");
                });
            }
            Task.WaitAll(instances);
        }
    }
}

如果不想使用非安全代码,可替换为以下转换逻辑:

GCHandle handle = GCHandle.Alloc(structBuf, GCHandleType.Pinned);
try
{
    receivedData = (Data)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(Data));
}
finally
{
    handle.Free();
}

注意事项

  • 禁止使用StreamReader/StreamWriter处理二进制数据,会触发隐式编码转换导致字节错乱
  • 两端结构体字段顺序、类型必须严格对应,Windows平台下C的unsigned int为32位无符号整数,对应C#的uint,不要误写为int
  • Windows平台下C和C#默认均为小端字节序,无需额外转换,跨平台场景需统一字节序
  • 如果C端使用#pragma pack修改了结构体对齐参数,C#端需要在StructLayout中指定对应Pack参数,例如[StructLayout(LayoutKind.Sequential, Pack = 1)]对应1字节对齐

内容的提问来源于stack exchange,提问作者Ganesh Kamath - 'Code Frenzy'

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 14:48:03